diff options
author | Mike Stump <mrs@gcc.gnu.org> | 1994-06-03 21:42:31 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 1994-06-03 21:42:31 +0000 |
commit | a0a339271ae588299147928769ca073a198d53c7 (patch) | |
tree | 2bfb1009d1a11061dfd6aad7e84a40e551c0af50 /gcc/cp | |
parent | 5345f91a0be605ab09f2f42abecd1a0fc5083f47 (diff) | |
download | gcc-a0a339271ae588299147928769ca073a198d53c7.zip gcc-a0a339271ae588299147928769ca073a198d53c7.tar.gz gcc-a0a339271ae588299147928769ca073a198d53c7.tar.bz2 |
39th Cygnus<->FSF merge
From-SVN: r7439
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 297 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 35 | ||||
-rw-r--r-- | gcc/cp/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/cp/call.c | 337 | ||||
-rw-r--r-- | gcc/cp/class.c | 92 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 70 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 14 | ||||
-rw-r--r-- | gcc/cp/decl.c | 238 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 60 | ||||
-rw-r--r-- | gcc/cp/error.c | 14 | ||||
-rw-r--r-- | gcc/cp/init.c | 2 | ||||
-rw-r--r-- | gcc/cp/lex.c | 16 | ||||
-rw-r--r-- | gcc/cp/lex.h | 1 | ||||
-rw-r--r-- | gcc/cp/method.c | 52 | ||||
-rw-r--r-- | gcc/cp/parse.y | 15 | ||||
-rw-r--r-- | gcc/cp/pt.c | 50 | ||||
-rw-r--r-- | gcc/cp/sig.c | 4 | ||||
-rw-r--r-- | gcc/cp/spew.c | 4 | ||||
-rw-r--r-- | gcc/cp/tree.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 232 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 135 |
21 files changed, 1080 insertions, 592 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f4b1424..385d239 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,289 @@ +Fri Jun 3 02:10:56 1994 Jason Merrill (jason@deneb.cygnus.com) + + * cvt.c (cp_convert): Replace constants with their values before + converting. + +Thu Jun 2 03:53:30 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck2.c (build_x_arrow): Resolve OFFSET_REFs first. + +Wed Jun 1 18:57:35 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck2.c (digest_init): Handle initializing a pmf with an + overloaded method. + * typeck.c (build_ptrmemfunc): Handle overloaded methods. + + * decl.c (pushtag): Use build_decl to make TYPE_DECLs. + (xref_defn_tag): Ditto. + * pt.c (process_template_parm): Ditto. + (lookup_template_class): Ditto. + (push_template_decls): Ditto. + (instantiate_class_template): Ditto. + (create_nested_upt): Ditto. + * class.c (finish_struct): Don't try to set DECL_CLASS_CONTEXT on + TYPE_DECLs. + + * typeck.c (convert_arguments): Make sure type is not NULL before + checking its TREE_CODE. + +Wed Jun 1 17:40:39 1994 Mike Stump (mrs@cygnus.com) + + * class.c (get_derived_offset): New routine. + * class.c (finish_base_struct): Make sure we set BINFO_VTABLE and + BINFO_VIRTUALS when we choose a new base class to inherit from. + * class.c (modify_one_vtable): Use get_derived_offset to get the + offset to the most base class subobject that we derived this binfo + from. + * class.c (finish_struct): Move code to calculate the + DECL_FIELD_BITPOS of the vfield up, as we need might need it for + new calls to get_derived_offset in modify_one_vtable. + +Wed Jun 1 16:50:59 1994 Jason Merrill (jason@deneb.cygnus.com) + + * init.c (build_member_call): Use build_pointer_type instead of + TYPE_POINTER_TO. + +Wed Jun 1 11:11:15 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + + * decl.c (grokdeclarator): Make sure we have a DNAME set before we + try to use it in an error. + +Wed Jun 1 09:48:49 1994 Mike Stump (mrs@cygnus.com) + + * typeck.c (convert_arguments, convert_for_initialization): Don't + strip NOP_EXPRs, when we are converting to a reference. + +Wed Jun 1 01:11:38 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck.c (build_modify_expr): Don't dereference references when + initializing them. + + * decl2.c (grokfield): Don't check for grokdeclarator returning + error_mark_node any more. + + * decl.c (grokfndecl): Return NULL_TREE instead of error_mark_node. + (start_method): Return void_type_node instead of error_mark_node. + + * typeck.c (build_modify_expr): Resolve offset refs earlier. + +Tue May 31 16:06:58 1994 Jason Merrill (jason@deneb.cygnus.com) + + * call.c (build_method_call): Resolve OFFSET_REFs in the object. + + * typeck.c (build_modify_expr): Dereference references before trying + to assign to them. + + * call.c (build_method_call): Don't confuse type conversion + operators with constructors. + * typeck2.c (build_functional_cast): Just call build_c_cast if there + was only one parameter. + * method.c (build_typename_overload): Don't set + IDENTIFIER_GLOBAL_VALUE on these identifiers. + * decl.c (grok_op_properties): Warn about defining a type conversion + operator that converts to a base class (or reference to it). + * cvt.c (cp_convert): Don't try to use a type conversion operator + when converting to a base class. + (build_type_conversion_1): Don't call constructor_name_full on an + identifier. + * cp-tree.h (DERIVED_FROM_P): Should be self-explanatory. + + * decl.c (start_decl): Don't complain that error_mark_node is an + incomplete type. + (finish_decl): Check for type == error_mark_node. + +Mon May 30 23:38:55 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl.c (start_function): Set DECL_DEFER_OUTPUT on implicit + instantiations and inline members. + + * spew.c (yylex): Set looking_for_template if the next token is a '<'. + + * lex.h: Declare looking_for_template. + + * decl.c (lookup_name_real): Use looking_for_template to arbitrate + between type and template interpretations of an identifier. + +Sat May 28 04:07:40 1994 Jason Merrill (jason@deneb.cygnus.com) + + * pt.c (instantiate_template): Zero out p if we found a + specialization. + + * decl.c (grokdeclarator): Elucidate warning. + (grokdeclarator): If pedantic AND -ansi, complain about long long. + + Make explicit instantiation work reasonably. It is now appropriate + to deprecate the use of -fexternal-templates. + * pt.c (instantiate_template): Set DECL_TEMPLATE_SPECIALIZATION or + DECL_IMPLICIT_INSTANTIATION on fndecl as appropriate. + (end_template_instantiation): Reflect changes in USE_TEMPLATE + semantics. + (do_pending_expansions): if (!flag_implicit_templates) DECIDE(0); + (do_function_instantiation): Don't set EXPLICIT_INST if + flag_external_templates is set. Do set TREE_PUBLIC and DECL_EXTERN + appropriately otherwise. + (do_type_instantiation): Set interface info for class. Set + TREE_PUBLIC and DECL_EXTERN for methods. Do none of this if + flag_external_templates is set. + * parse.y: Reflect changes in USE_TEMPLATE semantics. + * decl2.c: New flag flag_implicit_templates determines whether or + not implicit instantiations get emitted. This flag currently + defaults to true, and must be true for -fexternal-templates to work. + (finish_file): Consider flag_implement_inlines when + setting DECL_EXTERNAL. Consider flag_implicit_templates when + deciding whether or not to emit a static copy. + * decl.c (start_function): Set TREE_PUBLIC and DECL_EXTERNAL + properly for template instantiations. + (start_method): Set DECL_IMPLICIT_INSTANTIATION on methods of a + template class. + * cp-tree.h (CLASSTYPE_USE_TEMPLATE): Change semantics. + (DECL_USE_TEMPLATE): Parallel macro for FUNCTION and VAR_DECLs. + (various others): Accessor macros for the above. + +Fri May 27 13:57:40 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck.c (build_binary_op_nodefault): Division by constant zero is + an error. + +Fri May 27 13:50:15 1994 Mike Stump (mrs@cygnus.com) + + * class.c (override_one_vtable): Don't modify things we don't own. + +Fri May 27 01:42:58 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl.c (finish_decl): Don't postpone processing the initializer of + a decl with DECL_EXTERNAL set, and do call rest_of_compilation for a + PUBLIC const at toplevel. + (grokdeclarator): pedwarn about initializing non-const or + non-integral statics in the class body. + + * decl.c (pushtag): Don't try to set DECL_CLASS_CONTEXT on a + TYPE_DECL. + + * call.c (convert_harshness): Dereference reference on rhs before + proceeding, properly grok passing const things to non-const + references. + + * typeck.c (build_unary_op): Soften error about taking the address + of main() to a pedwarn. + + * lex.c (default_copy_constructor_body): Unambiguously specify base + classes (i.e. A((const class ::A&)_ctor_arg) ). + (default_assign_ref_body): Ditto. + +Thu May 26 13:13:55 1994 Gerald Baumgartner (gb@mexican.cygnus.com) + + * decl2.c (grokfield): Don't complain about local signature + method declaration without definition. + + * call.c (convert_harshness): If `type' is a signature pointer + and `parmtype' is a pointer to a signature, just return 0. We + don't really convert in this case; it's a result of making the + `this' parameter of a signature method a signature pointer. + + * call.c (build_method_call): Distinguish calling the default copy + constructor of a signature pointer/reference from a signature + member function call. + +Thu May 26 12:56:25 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl2.c (grokfield): Don't set TREE_PUBLIC on member function + declarations. + + * decl.c (duplicate_decls): A previous function declaration as + static overrides a subsequent non-static definition. + (grokdeclarator): Don't set TREE_PUBLIC on inline method + declarations. + +Wed May 25 14:36:38 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl.c (grokdeclarator): Handle initialization of static const + members. + (finish_decl): Ditto. + + * decl2.c (grokfield): Allow initialization of static const members + even when pedantic. + + * decl2.c (grokfield): Deal with grokdeclarator returning + error_mark_node. + + * decl.c (grok_ctor_properties): Return 0 for A(A) constructor. + (grokfndecl): Check the return value of grok_ctor_properties. + (start_method): Ditto. + + * parse.y (absdcl): Expand type_quals inline. + +Tue May 24 19:10:32 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl.c (pushtag): Use IS_AGGR_TYPE rather than checking for a + RECORD_TYPE. + +Tue May 24 18:09:16 1994 Per Bothner (bothner@kalessin.cygnus.com) + + * cp-tree.h (VTABLE_NAME_FORMAT): If flag_vtable_thunks, + always use "__vt_%s". + * decl2.c (finish_vtable_vardecl): Don't consider abstract virtuals + when looking for a "sentinal" method (to decide on emitting vtables). + * decl2.c (finish_file): Scan all decls for thunks that need + to be emitted. + * decl2.c (finish_vtable_vardecl): Don't bother calling emit_thunk. + * method.c (make_thunk): Use a more meaningful label. If there + exists a matching top-level THUNK_DECL re-use it; otherwise + create a new THUNK_DECL (and declare it). + * method.c (emit_thunk): Make thunk external/public depending + on the underlying method. + +Tue May 24 00:22:04 1994 Jason Merrill (jason@deneb.cygnus.com) + + * pt.c (tsubst): Use lookup_name_nonclass to find guiding decls, not + lookup_name. + + * call.c (build_overload_call_real): Don't immediately pick a + function which matches perfectly. + + * decl.c (grokdeclarator): Use c_build_type_variant for arrays. + (grokdeclarator): Warn about, and throw away, cv-quals attached to a + reference (like 'int &const j'). + + * typeck.c (convert_arguments): Don't mess with i for methods. + * call.c (build_method_call): Pass the function decl to + convert_arguments. + + * typeck.c (comp_ptr_ttypes_real): New function. Implements the + checking for which multi-level pointer conversions are allowed. + (comp_target_types): Call it. + (convert_for_assignment): Check const parity on the ultimate target + type, too. And make those warnings pedwarns. + +Mon May 23 14:11:24 1994 Jason Merrill (jason@deneb.cygnus.com) + + * error.c (dump_char): Use TARGET_* for character constants. + +Mon May 23 13:03:03 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + + * tree.c (debug_no_list_hash): Make static. + + * decl.c (decls_match): Say the types don't match if newdecl ends up + with a null type, after we've checked if olddecl does. + (pushdecl): Check if the decls themselves match before looking for + an extern redeclared as static, to avoid inappropriate and incorrect + warnings. + +Fri May 20 14:04:34 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl.c (grokdeclarator): Make warning about duplicate short, etc. + a pedwarn. + + * typeck.c (build_c_cast): Casting to function or method type is an + error. + + * class.c (finish_struct): Make warning for anonymous class with no + instances a pedwarn. + + * Makefile.in (stamp-parse): Expect a s/r conflict. + + * typeck.c (build_modify_expr): pedwarn about using a non-lvalue + cast as an lvalue. + Thu May 19 12:08:48 1994 Jason Merrill (jason@deneb.cygnus.com) * cvt.c (type_promotes_to): Make sure bool promotes to int rather @@ -30,17 +316,6 @@ Wed May 18 14:27:06 1994 Jason Merrill (jason@deneb.cygnus.com) * class.c (finish_struct): Allow bool bitfields. -Wed May 18 14:41:59 1994 Mike Stump (mrs@cygnus.com) - - * class.c (finish_base_struct): Make sure we set BINFO_VTABLE and - BINFO_VIRTUALS when we choose a new base class to inherit from. - * class.c (modify_one_vtable): Use get_vfield_offset to get the - offset to the most base class subobject that we derived this binfo - from. - * class.c (finish_struct): Move code to calculate the - DECL_FIELD_BITPOS of the vfield up, as we need might need it for - new calls to get_vfield_offset in modify_one_vtable. - Wed May 18 12:35:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * Make-lang.in (c++.install-man): Get g++.1 from $(srcdir)/cp. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 0bf1b78..b888289 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -41,6 +41,15 @@ CXX_FLAGS_TO_PASS = \ "CXXFLAGS=$(CXXFLAGS)" \ "CXX_FOR_TARGET=$(CXX_FOR_TARGET)" +# Actual names to use when installing a native compiler. +CXX_INSTALL_NAME = c++ +GXX_INSTALL_NAME = g++ + +# Actual names to use when installing a cross-compiler. +CXX_CROSS_NAME = $(target)-c++ +GXX_CROSS_NAME = $(target)-g++ + + # Define the names for selecting c++ in LANGUAGES. # Note that it would be nice to move the dependency on g++ # into the C++ rule, but that needs a little bit of work @@ -90,17 +99,17 @@ c++.install-normal: c++.install-common: -if [ -f cc1plus ] ; then \ if [ -f g++-cross ] ; then \ - rm -f $(bindir)/$(target)-g++; \ - $(INSTALL_PROGRAM) g++-cross $(bindir)/$(target)-g++; \ - chmod a+x $(bindir)/$(target)-g++; \ - rm -f $(bindir)/$(target)-c++; \ - ln $(bindir)/$(target)-g++ $(bindir)/$(target)-c++; \ + rm -f $(bindir)/$(GXX_CROSS_NAME); \ + $(INSTALL_PROGRAM) g++-cross $(bindir)/$(GXX_CROSS_NAME); \ + chmod a+x $(bindir)/$(GXX_CROSS_NAME); \ + rm -f $(bindir)/$(CXX_CROSS_NAME); \ + ln $(bindir)/$(GXX_CROSS_NAME) $(bindir)/$(CXX_CROSS_NAME); \ else \ - rm -f $(bindir)/g++; \ - $(INSTALL_PROGRAM) g++ $(bindir)/g++; \ - chmod a+x $(bindir)/g++; \ - rm -f $(bindir)/c++; \ - ln $(bindir)/g++ $(bindir)/c++; \ + rm -f $(bindir)/$(GXX_INSTALL_NAME); \ + $(INSTALL_PROGRAM) g++ $(bindir)/$(GXX_INSTALL_NAME); \ + chmod a+x $(bindir)/$(GXX_INSTALL_NAME); \ + rm -f $(bindir)/$(CXX_INSTALL_NAME); \ + ln $(bindir)/$(GXX_INSTALL_NAME) $(bindir)/$(CXX_INSTALL_NAME); \ fi ; \ fi @@ -113,8 +122,10 @@ c++.install-man: $(srcdir)/cp/g++.1 else true; fi c++.uninstall: - -rm -rf $(bindir)/g++ $(bindir)/c++ - -rm -rf $(bindir)/$(target)-g++ $(bindir)/$(target)-c++ + -rm -rf $(bindir)/$(CXX_INSTALL_NAME) + -rm -rf $(bindir)/$(CXX_CROSS_NAME) + -rm -rf $(bindir)/$(GXX_INSTALL_NAME) + -rm -rf $(bindir)/$(GXX_CROSS_NAME) -rm -rf $(mandir)/g++$(manext) # Clean hooks: diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index 120e330..231d1a3 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -193,7 +193,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h `echo $(srcdir)/parse.c | sed 's,^\./,,'` $(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y - @echo expect 33 reduce/reduce conflicts. + @echo expect 1 shift/reduce confict and 33 reduce/reduce conflicts. cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e957776..6d2b26c 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -131,6 +131,13 @@ convert_harshness (type, parmtype, parm) if (TYPE_PTRMEMFUNC_P (parmtype)) parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype); + if (TREE_CODE (parmtype) == REFERENCE_TYPE) + { + if (parm) + parm = convert_from_reference (parm); + parmtype = TREE_TYPE (parmtype); + } + codel = TREE_CODE (type); coder = TREE_CODE (parmtype); @@ -474,196 +481,138 @@ convert_harshness (type, parmtype, parm) } } - /* C++: one of the types must be a reference type. */ - { - tree ttl, ttr; - register tree intype = TYPE_MAIN_VARIANT (parmtype); - register enum tree_code form = TREE_CODE (intype); - int penalty = 0; - - if (codel == REFERENCE_TYPE || coder == REFERENCE_TYPE) - { - ttl = TYPE_MAIN_VARIANT (type); - - if (codel == REFERENCE_TYPE) - { - ttl = TREE_TYPE (ttl); + /* C++: Since the `this' parameter of a signature member function + is represented as a signature pointer to handle default implementations + correctly, we can have the case that `type' is a signature pointer + while `parmtype' is a pointer to a signature table. We don't really + do any conversions in this case, so just return 0. */ - /* When passing a non-const argument into a const reference, - dig it a little, so a non-const reference is preferred over - this one. (mrs) */ - if (parm && TREE_READONLY (ttl) && ! TREE_READONLY (parm)) - penalty = 2; - else - penalty = 0; + if (codel == RECORD_TYPE && coder == POINTER_TYPE + && IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype))) + return ZERO_RETURN (h); - ttl = TYPE_MAIN_VARIANT (ttl); + if (codel == REFERENCE_TYPE) + { + tree ttl, ttr; + int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype); + int volatilep = (parm ? TREE_THIS_VOLATILE (parm) + : TYPE_VOLATILE (parmtype)); + register tree intype = TYPE_MAIN_VARIANT (parmtype); + register enum tree_code form = TREE_CODE (intype); + int penalty = 0; + + ttl = TREE_TYPE (type); + + /* When passing a non-const argument into a const reference (or vice + versa), dig it a little, so a non-const reference is preferred + over this one. (mrs) */ + if (TYPE_READONLY (ttl) != constp + || TYPE_VOLATILE (ttl) != volatilep) + penalty = 2; + else + penalty = 0; - if (form == OFFSET_TYPE) - { - intype = TREE_TYPE (intype); - form = TREE_CODE (intype); - } + ttl = TYPE_MAIN_VARIANT (ttl); - if (form == REFERENCE_TYPE) - { - intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype)); + if (form == OFFSET_TYPE) + { + intype = TREE_TYPE (intype); + form = TREE_CODE (intype); + } - if (ttl == intype) - return ZERO_RETURN (h); - penalty = 2; - } - else - { - /* Can reference be built up? */ - if (ttl == intype && penalty == 0) { - /* Because the READONLY and VIRTUAL bits are not always in - the type, this extra check is necessary. The problem - should be fixed someplace else, and this extra code - removed. - - Also, if type if a reference, the readonly bits could - either be in the outer type (with reference) or on the - inner type (the thing being referenced). (mrs) */ - if (parm - && ((TREE_READONLY (parm) - && ! (TYPE_READONLY (type) - || (TREE_CODE (type) == REFERENCE_TYPE - && TYPE_READONLY (TREE_TYPE (type))))) - || (TREE_SIDE_EFFECTS (parm) - && ! (TYPE_VOLATILE (type) - || (TREE_CODE (type) == REFERENCE_TYPE - && TYPE_VOLATILE (TREE_TYPE (type))))))) - penalty = 2; - else - return ZERO_RETURN (h); - } - else - penalty = 2; - } - } - else if (form == REFERENCE_TYPE) - { - if (parm) - { - tree tmp = convert_from_reference (parm); - intype = TYPE_MAIN_VARIANT (TREE_TYPE (tmp)); - } - else - { - intype = parmtype; - do - intype = TREE_TYPE (intype); - while (TREE_CODE (intype) == REFERENCE_TYPE); - intype = TYPE_MAIN_VARIANT (intype); - } - - if (ttl == intype) - return ZERO_RETURN (h); - else - penalty = 2; - } + if (ttl == intype && penalty == 0) + return ZERO_RETURN (h); + else + penalty = 2; - if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype)) - { - ttl = unsigned_type (ttl); - intype = unsigned_type (intype); - penalty += 2; - } + if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype)) + { + ttl = unsigned_type (ttl); + intype = unsigned_type (intype); + penalty += 2; + } - ttr = intype; + ttr = intype; - /* If the initializer is not an lvalue, then it does not - matter if we make life easier for the programmer - by creating a temporary variable with which to - hold the result. */ - if (parm && (INTEGRAL_CODE_P (coder) - || coder == REAL_TYPE) - && ! lvalue_p (parm)) - { - h = convert_harshness (ttl, ttr, NULL_TREE); - if (penalty > 2 || h.code != 0) - h.code |= STD_CODE; - else - h.code |= TRIVIAL_CODE; - h.distance = 0; - return h; - } + /* If the initializer is not an lvalue, then it does not + matter if we make life easier for the programmer + by creating a temporary variable with which to + hold the result. */ + if (parm && (INTEGRAL_CODE_P (coder) + || coder == REAL_TYPE) + && ! lvalue_p (parm)) + { + h = convert_harshness (ttl, ttr, NULL_TREE); + if (penalty > 2 || h.code != 0) + h.code |= STD_CODE; + else + h.code |= TRIVIAL_CODE; + h.distance = 0; + return h; + } - if (ttl == ttr) - { - if (penalty > 2) - { - h.code = STD_CODE; - h.distance = 0; - } - else - { - h.code = TRIVIAL_CODE; - /* We set this here so that build_overload_call_real will be - able to see the penalty we found, rather than just looking - at a TRIVIAL_CODE with no other information. */ - h.int_penalty = penalty; - } - return h; - } + if (ttl == ttr) + { + if (penalty > 2) + { + h.code = STD_CODE; + h.distance = 0; + } + else + { + h.code = TRIVIAL_CODE; + /* We set this here so that build_overload_call_real will be + able to see the penalty we found, rather than just looking + at a TRIVIAL_CODE with no other information. */ + h.int_penalty = penalty; + } + return h; + } - /* Pointers to voids always convert for pointers. But - make them less natural than more specific matches. */ - if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE) - { - if (TREE_TYPE (ttl) == void_type_node - || TREE_TYPE (ttr) == void_type_node) - { - h.code = STD_CODE; - h.distance = 0; - return h; - } - } + /* Pointers to voids always convert for pointers. But + make them less natural than more specific matches. */ + if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE) + { + if (TREE_TYPE (ttl) == void_type_node + || TREE_TYPE (ttr) == void_type_node) + { + h.code = STD_CODE; + h.distance = 0; + return h; + } + } - if (parm && codel != REFERENCE_TYPE) - { - h = convert_harshness (ttl, ttr, NULL_TREE); - if (penalty == 2) - h.code |= QUAL_CODE; - else if (penalty == 4) - h.code |= STD_CODE; - h.distance = 0; - return h; - } + /* Here it does matter. If this conversion is from derived to base, + allow it. Otherwise, types must be compatible in the strong sense. */ + if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE) + { + int b_or_d = get_base_distance (ttl, ttr, 0, 0); + if (b_or_d < 0) + { + b_or_d = get_base_distance (ttr, ttl, 0, 0); + if (b_or_d < 0) + return EVIL_RETURN (h); + h.distance = -b_or_d; + } + /* Say that this conversion is relatively painless. + If it turns out that there is a user-defined X(X&) + constructor, then that will be invoked, but that's + preferable to dealing with other user-defined conversions + that may produce surprising results. */ + else + h.distance = b_or_d; + h.code = STD_CODE; + return h; + } - /* Here it does matter. If this conversion is from derived to base, - allow it. Otherwise, types must be compatible in the strong sense. */ - if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE) - { - int b_or_d = get_base_distance (ttl, ttr, 0, 0); - if (b_or_d < 0) - { - b_or_d = get_base_distance (ttr, ttl, 0, 0); - if (b_or_d < 0) - return EVIL_RETURN (h); - h.distance = -b_or_d; - } - /* Say that this conversion is relatively painless. - If it turns out that there is a user-defined X(X&) - constructor, then that will be invoked, but that's - preferable to dealing with other user-defined conversions - that may produce surprising results. */ - else - h.distance = b_or_d; + if (comp_target_types (ttl, intype, 1)) + { + if (penalty) h.code = STD_CODE; - return h; - } - - if (comp_target_types (ttl, intype, 1)) - { - if (penalty) - h.code = STD_CODE; - h.distance = 0; - return h; - } - } - } + h.distance = 0; + return h; + } + } if (codel == RECORD_TYPE && coder == RECORD_TYPE) { int b_or_d = get_base_distance (type, parmtype, 0, 0); @@ -1789,6 +1738,9 @@ build_method_call (instance, name, parms, basetype_path, flags) && TREE_CODE (TREE_OPERAND (instance, 0)) == NOP_EXPR && TREE_OPERAND (TREE_OPERAND (instance, 0), 0) == error_mark_node); + if (TREE_CODE (instance) == OFFSET_REF) + instance = resolve_offset_ref (instance); + /* the base type of an instance variable is pointer to class */ basetype = TREE_TYPE (instance); @@ -1808,8 +1760,12 @@ build_method_call (instance, name, parms, basetype_path, flags) if (! IS_AGGR_TYPE (basetype)) goto non_aggr_error; - if (IS_SIGNATURE_POINTER (basetype) - || IS_SIGNATURE_REFERENCE (basetype)) + /* If `instance' is a signature pointer/reference and `name' is + not a constructor, we are calling a signature member function. + In that case set the `basetype' to the signature type. */ + if ((IS_SIGNATURE_POINTER (basetype) + || IS_SIGNATURE_REFERENCE (basetype)) + && TYPE_IDENTIFIER (basetype) != name) basetype = SIGNATURE_TYPE (basetype); if ((IS_SIGNATURE (basetype) @@ -2001,8 +1957,9 @@ build_method_call (instance, name, parms, basetype_path, flags) /* Look up function name in the structure type definition. */ if ((IDENTIFIER_HAS_TYPE_VALUE (name) + && ! IDENTIFIER_OPNAME_P (name) && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name)) - && TREE_CODE(IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE) + && TREE_CODE (IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE) || name == constructor_name (basetype)) { tree tmp = NULL_TREE; @@ -2494,11 +2451,9 @@ build_method_call (instance, name, parms, basetype_path, flags) return error_mark_node; } - /* We do not pass FUNCTION into `convert_arguments', because by - now everything should be ok. If not, then we have a serious error. */ if (DECL_STATIC_FUNCTION_P (function)) parms = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype), - TREE_CHAIN (parms), NULL_TREE, LOOKUP_NORMAL); + TREE_CHAIN (parms), function, LOOKUP_NORMAL); else if (need_vtbl == unneeded) { int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL; @@ -2511,7 +2466,7 @@ build_method_call (instance, name, parms, basetype_path, flags) instance = build_indirect_ref (instance_ptr, NULL_PTR); } parms = tree_cons (NULL_TREE, instance_ptr, - convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), NULL_TREE, sub_flags)); + convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, sub_flags)); } else { @@ -2559,7 +2514,7 @@ build_method_call (instance, name, parms, basetype_path, flags) instance = build_indirect_ref (instance_ptr, NULL_PTR); } parms = tree_cons (NULL_TREE, instance_ptr, - convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), NULL_TREE, LOOKUP_NORMAL)); + convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, LOOKUP_NORMAL)); } #if 0 @@ -2861,18 +2816,6 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) if ((cp[0].h.code & EVIL_CODE) == 0) { cp[1].h.code = EVIL_CODE; - - /* int_penalty is set by convert_harshness_ansi for cases - where we need to know about any penalties that would - otherwise make a TRIVIAL_CODE pass. */ - if (final_cp - && template_cost == 0 - && cp[0].h.code <= TRIVIAL_CODE - && cp[0].h.int_penalty == 0) - { - final_cp[0].h = cp[0].h; - return function; - } cp++; } } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4fab523..638fedf 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1123,6 +1123,24 @@ get_vfield_offset (binfo) BINFO_OFFSET (binfo)); } +/* Get the offset to the start of the original binfo that we derived this + binfo from. */ +tree get_derived_offset (binfo) + tree binfo; +{ + tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); + tree offset2; + int i; + while (BINFO_BASETYPES (binfo) + && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) + { + tree binfos = BINFO_BASETYPES (binfo); + binfo = TREE_VEC_ELT (binfos, i); + } + offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); + return size_binop (MINUS_EXPR, offset1, offset2); +} + /* If FOR_TYPE needs to reinitialize virtual function table pointers for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST. Returns BASE_INIT_LIST appropriately modified. */ @@ -2171,8 +2189,13 @@ modify_one_vtable (binfo, t, fndecl, pfn) /* Find the right offset for the this pointer based on the base class we just found. We have to take into consideration the virtual base class pointers that we - stick in before the virtual function table pointer. */ - base_offset = get_vfield_offset (binfo); + stick in before the virtual function table pointer. + + Also, we want just the delta bewteen the most base class + that we derived this vfield from and us. */ + base_offset = size_binop (PLUS_EXPR, + get_derived_offset (binfo), + BINFO_OFFSET (binfo)); this_offset = size_binop (MINUS_EXPR, offset, base_offset); /* Make sure we can modify the derived association with immunity. */ @@ -2374,8 +2397,8 @@ override_one_vtable (binfo, old, t) override_one_vtable (binfo, old, t); return; } + TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals); } - TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals); } else { @@ -2547,7 +2570,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) int ref_sans_init = 0; int nonprivate_method = 0; tree t_binfo = TYPE_BINFO (t); - tree access_decls = 0; + tree access_decls = NULL_TREE; if (TREE_CODE (name) == TYPE_DECL) { @@ -2578,7 +2601,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) } if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name)) - warning ("anonymous class type not used to declare any objects"); + pedwarn ("anonymous class type not used to declare any objects"); if (TYPE_SIZE (t)) { @@ -2599,7 +2622,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) /* If this type was previously laid out as a forward reference, make sure we lay it out again. */ - TYPE_SIZE (t) = 0; + TYPE_SIZE (t) = NULL_TREE; CLASSTYPE_GOT_SEMICOLON (t) = 0; /* A signature type will contain the fields of the signature table. @@ -3025,7 +3048,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (code == UNION_TYPE) { - char * fie = 0; + char *fie = NULL; if (TYPE_NEEDS_CONSTRUCTING (type)) fie = "constructor"; else if (TYPE_NEEDS_DESTRUCTOR (type)) @@ -3252,9 +3275,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name) { cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); - cp_error_at ("because of local method `%#D' with same name", + cp_error_at (" because of local method `%#D' with same name", TREE_VEC_ELT (method_vec, i)); - fdecl = 0; + fdecl = NULL_TREE; break; } @@ -3265,8 +3288,8 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (DECL_NAME (tmp) == name) { cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); - cp_error_at ("because of local field `%#D' with same name", tmp); - fdecl = 0; + cp_error_at (" because of local field `%#D' with same name", tmp); + fdecl = NULL_TREE; break; } @@ -3315,7 +3338,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) } else if (last_x) { - my_friendly_assert (TREE_CHAIN (last_x) == 0, 175); + my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175); TREE_CHAIN (last_x) = vfield; last_x = vfield; } @@ -3378,7 +3401,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) moved into the type of this field, but nothing seems to break by doing this. */ - if (DECL_NAME (field) == 0 + if (DECL_NAME (field) == NULL_TREE && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) { tree uelt = TYPE_FIELDS (TREE_TYPE (field)); @@ -3405,7 +3428,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) TYPE_ALIGN (pseudo_basetype) = CLASSTYPE_ALIGN (t); DECL_ALIGN (base_layout_decl) = TYPE_ALIGN (pseudo_basetype); /* Don't re-use old size. */ - DECL_SIZE (base_layout_decl) = 0; + DECL_SIZE (base_layout_decl) = NULL_TREE; } layout_type (t); @@ -3432,7 +3455,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) moved into the type of this field, but nothing seems to break by doing this. */ - if (DECL_NAME (field) == 0 + if (DECL_NAME (field) == NULL_TREE && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) { tree uelt = TYPE_FIELDS (TREE_TYPE (field)); @@ -3709,12 +3732,11 @@ finish_struct (t, list_of_fieldlists, warn_anon) while (x) { #if 0 /* What's wrong with using the decl the type already has? */ - tree tag = build_lang_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x)); + tree tag = build_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x)); DECL_CONTEXT (tag) = t; #else tree tag = TYPE_NAME (TREE_VALUE (x)); #endif - DECL_CLASS_CONTEXT (tag) = t; #ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) @@ -3729,7 +3751,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) x = TREE_CHAIN (x); last_x = chainon (last_x, tag); } - if (TYPE_FIELDS (t) == 0) + if (TYPE_FIELDS (t) == NULL_TREE) TYPE_FIELDS (t) = last_x; CLASSTYPE_LOCAL_TYPEDECLS (t) = 1; } @@ -4220,7 +4242,9 @@ popclass (modify) { if (CLASSTYPE_VTBL_PTR (current_class_type)) { - current_vtable_decl = lookup_name (DECL_NAME (CLASSTYPE_VTBL_PTR (current_class_type)), 0); + current_vtable_decl + = lookup_name (DECL_NAME (CLASSTYPE_VTBL_PTR (current_class_type)), + 0); if (current_vtable_decl) current_vtable_decl = build_indirect_ref (current_vtable_decl, NULL_PTR); @@ -4525,9 +4549,10 @@ instantiate_type (lhstype, rhs, complain) { if (complain) { - cp_error ("cannot resolve overload to target type `%#T';", lhstype); - cp_error_at ("ambiguity between `%#D'", save_elem); - cp_error_at ("and `%#D', at least", elem); + cp_error ("cannot resolve overload to target type `%#T'", + lhstype); + cp_error_at (" ambiguity between `%#D'", save_elem); + cp_error_at (" and `%#D', at least", elem); } return error_mark_node; } @@ -4547,9 +4572,9 @@ instantiate_type (lhstype, rhs, complain) } if (complain) { - cp_error ("cannot resolve overload to target type `%#T';", + cp_error ("cannot resolve overload to target type `%#T'", lhstype); - cp_error ("no suitable overload of function `%D' exists", + cp_error (" because no suitable overload of function `%D' exists", TREE_PURPOSE (rhs)); } return error_mark_node; @@ -4631,10 +4656,12 @@ instantiate_type (lhstype, rhs, complain) case PLUS_EXPR: case MINUS_EXPR: case COMPOUND_EXPR: - TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); + TREE_OPERAND (rhs, 0) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); if (TREE_OPERAND (rhs, 0) == error_mark_node) return error_mark_node; - TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain); + TREE_OPERAND (rhs, 1) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain); if (TREE_OPERAND (rhs, 1) == error_mark_node) return error_mark_node; @@ -4701,10 +4728,12 @@ instantiate_type (lhstype, rhs, complain) error ("not enough type information"); return error_mark_node; } - TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain); + TREE_OPERAND (rhs, 1) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain); if (TREE_OPERAND (rhs, 1) == error_mark_node) return error_mark_node; - TREE_OPERAND (rhs, 2) = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain); + TREE_OPERAND (rhs, 2) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain); if (TREE_OPERAND (rhs, 2) == error_mark_node) return error_mark_node; @@ -4712,7 +4741,8 @@ instantiate_type (lhstype, rhs, complain) return rhs; case MODIFY_EXPR: - TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain); + TREE_OPERAND (rhs, 1) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain); if (TREE_OPERAND (rhs, 1) == error_mark_node) return error_mark_node; @@ -4730,8 +4760,8 @@ instantiate_type (lhstype, rhs, complain) } TREE_TYPE (rhs) = lhstype; lhstype = TREE_TYPE (lhstype); - TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), - complain); + TREE_OPERAND (rhs, 0) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); if (TREE_OPERAND (rhs, 0) == error_mark_node) return error_mark_node; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 061c7f1..7ae511f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -362,6 +362,7 @@ enum languages { lang_c, lang_cplusplus }; #define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) >= 0) #define ACCESSIBLY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, -1, (tree *)0) >= 0) #define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 1, (tree *)0) >= 0) +#define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1) enum conversion_type { ptr_conv, constptr_conv, int_conv, real_conv, last_conversion_type }; @@ -497,8 +498,11 @@ struct lang_type union tree_node *signature_reference_to; }; -/* Indicates whether a template should be (or has been) expanded for this - class definition. 0=do, 1=did, 2=don't, 3=didn't. */ +/* Indicates whether or not (and how) a template was expanded for this class. + 0=no information yet/non-template class + 1=implicit template instantiation + 2=explicit template specialization + 3=explicit template instantiation */ #define CLASSTYPE_USE_TEMPLATE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.use_template) /* Fields used for storing information before the class is defined. @@ -931,7 +935,9 @@ struct lang_decl_flags unsigned mutable_flag : 1; unsigned is_default_implementation : 1; unsigned saved_inline : 1; - unsigned dummy : 10; + unsigned use_template : 2; + + unsigned dummy : 8; tree access; tree context; @@ -1101,7 +1107,7 @@ struct lang_decl #if 0 /* Same, but tells if this field is private in current context. */ -#define DECL_PRIVATE(NODE) NOTHING +#define DECL_PRIVATE(NODE) (DECL_LANG_FLAG_5 (NODE)) /* Same, but tells if this field is private in current context. */ #define DECL_PROTECTED(NODE) (DECL_LANG_FLAG_6 (NODE)) @@ -1266,11 +1272,39 @@ struct lang_decl #define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE) #define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE) -/* Macros for a DECL or TYPE generated from a template to indicate that it - was explicitly instantiated. */ -#define DECL_EXPLICITLY_INSTANTIATED(NODE) (DECL_LANG_FLAG_5 (NODE)) -#define CLASSTYPE_EXPLICITLY_INSTANTIATED(NODE) \ - (DECL_EXPLICITLY_INSTANTIATED (TYPE_NAME (NODE))) +/* Indicates whether or not (and how) a template was expanded for this + FUNCTION_DECL or VAR_DECL. + 0=normal declaration, e.g. int min (int, int); + 1=implicit template instantiation + 2=explicit template specialization, e.g. int min<int> (int, int); + 3=explicit template instantiation, e.g. template int min<int> (int, int); + */ +#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.use_template) + +#define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1) +#define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE (NODE) & 1) + +#define DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) == 2) +#define SET_DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) = 2) +#define CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE (NODE) == 2) +#define SET_CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE (NODE) = 2) + +#define DECL_IMPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) == 1) +#define SET_DECL_IMPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) = 1) +#define CLASSTYPE_IMPLICIT_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE(NODE) == 1) +#define SET_CLASSTYPE_IMPLICIT_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE(NODE) = 1) + +#define DECL_EXPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) == 3) +#define SET_DECL_EXPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) = 3) +#define CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE(NODE) == 3) +#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE(NODE) = 3) #define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i) @@ -1309,6 +1343,7 @@ extern void check_function_format PROTO((tree, tree, tree)); /* Print an error message for invalid operands to arith operation CODE. NOP_EXPR is used as a special case (see truthvalue_conversion). */ extern void binary_op_error PROTO((enum tree_code)); +extern tree c_build_type_variant PROTO((tree, int, int)); extern void c_expand_expr_stmt PROTO((tree)); /* Validate the expression after `case' and apply default promotions. */ extern tree check_case_value PROTO((tree)); @@ -1462,7 +1497,7 @@ extern int current_function_parms_stored; #define AUTO_TEMP_NAME "_$tmp_" #define AUTO_TEMP_FORMAT "_$tmp_%d" #define VTABLE_BASE "$vb" -#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT$%s" : "_vt$%s") +#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt$%s") #define VFIELD_BASE "$vf" #define VFIELD_NAME "_vptr$" #define VFIELD_NAME_FORMAT "_vptr$%s" @@ -1484,7 +1519,7 @@ extern int current_function_parms_stored; #define AUTO_TEMP_NAME "_.tmp_" #define AUTO_TEMP_FORMAT "_.tmp_%d" #define VTABLE_BASE ".vb" -#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT.%s" : "_vt.%s") +#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt.%s") #define VFIELD_BASE ".vf" #define VFIELD_NAME "_vptr." #define VFIELD_NAME_FORMAT "_vptr.%s" @@ -1513,7 +1548,7 @@ extern int current_function_parms_stored; #define AUTO_TEMP_FORMAT "__tmp_%d" #define VTABLE_BASE "__vtb" #define VTABLE_NAME "__vt_" -#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT_%s" : "_vt_%s") +#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt_%s") #define VTABLE_NAME_P(ID_NODE) \ (!strncmp (IDENTIFIER_POINTER (ID_NODE), VTABLE_NAME, \ sizeof (VTABLE_NAME) - 1)) @@ -1668,6 +1703,11 @@ extern int flag_gc; extern int flag_dossier; +/* Nonzero means do emit exported implementations of functions even if + they can be inlined. */ + +extern int flag_implement_inlines; + /* Nonzero means templates obey #pragma interface and implementation. */ extern int flag_external_templates; @@ -1676,6 +1716,10 @@ extern int flag_external_templates; extern int flag_alt_external_templates; +/* Nonzero means implicit template instantatiations are emitted. */ + +extern int flag_implicit_templates; + /* Current end of entries in the gc obstack for stack pointer variables. */ extern int current_function_obstack_index; @@ -1875,7 +1919,7 @@ extern tree lookup_name_current_level PROTO((tree)); extern void init_decl_processing PROTO((void)); /* skipped define_function */ extern void shadow_tag PROTO((tree)); -extern void grok_ctor_properties PROTO((tree, tree)); +extern int grok_ctor_properties PROTO((tree, tree)); extern tree groktypename PROTO((tree)); extern tree start_decl PROTO((tree, tree, int, tree)); extern void finish_decl PROTO((tree, tree, tree, int)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 7bfe802..fc8d261 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -1226,6 +1226,9 @@ cp_convert (type, expr, convtype, flags) else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) e = convert_from_reference (e); + if (TREE_READONLY_DECL_P (e)) + e = decl_constant_value (e); + if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (expr); @@ -1332,8 +1335,12 @@ cp_convert (type, expr, convtype, flags) { tree binfo; - tree conversion = TYPE_HAS_CONVERSION (dtype) - ? build_type_conversion (CONVERT_EXPR, type, e, 1) : NULL_TREE; + tree conversion; + + if (! DERIVED_FROM_P (type, dtype) && TYPE_HAS_CONVERSION (dtype)) + conversion = build_type_conversion (CONVERT_EXPR, type, e, 1); + else + conversion = NULL_TREE; if (TYPE_HAS_CONSTRUCTOR (type)) { @@ -1493,8 +1500,7 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure) else flags = LOOKUP_NORMAL; - rval = build_method_call (first_arg, constructor_name_full (typename), - NULL_TREE, NULL_TREE, flags); + rval = build_method_call (first_arg, typename, NULL_TREE, NULL_TREE, flags); if (rval == error_mark_node) { if (for_sure == 0) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index fd73388..10e9d0e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -410,11 +410,6 @@ extern int flag_short_double; extern int flag_no_builtin; -/* Nonzero means do emit exported implementations of functions even if - they can be inlined. */ - -extern int flag_implement_inlines; - /* Nonzero means disable GNU extensions. */ extern int flag_ansi; @@ -1791,7 +1786,7 @@ pushtag (name, type, globalize) { /* Make nested declarations go into class-level scope. */ newdecl = 1; - d = build_lang_field_decl (TYPE_DECL, name, type); + d = build_decl (TYPE_DECL, name, type); #ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) { @@ -1832,14 +1827,13 @@ pushtag (name, type, globalize) } /* else if (TYPE_SIZE (current_class_type) == NULL_TREE) */ - else if (context && TREE_CODE (context) == RECORD_TYPE) + else if (context && IS_AGGR_TYPE (context)) { /* Class-nested class. */ set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl), name, type); /* This builds the links for classes nested in type scope. */ DECL_CONTEXT (d) = context; - DECL_CLASS_CONTEXT (d) = context; } TYPE_CONTEXT (type) = DECL_CONTEXT (d); if (newdecl) @@ -2021,6 +2015,8 @@ decls_match (newdecl, olddecl) types_match = TREE_TYPE (olddecl) == error_mark_node; else if (TREE_TYPE (olddecl) == NULL_TREE) types_match = TREE_TYPE (newdecl) == NULL_TREE; + else if (TREE_TYPE (newdecl) == NULL_TREE) + types_match = 0; else types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1); } @@ -2441,18 +2437,7 @@ duplicate_decls (newdecl, olddecl) TREE_STATIC (newdecl) = TREE_STATIC (olddecl); DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); - /* For functions, static overrides non-static. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL) - { - TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); - /* This is since we don't automatically - copy the attributes of NEWDECL into OLDDECL. */ - TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); - /* If this clears `static', clear it in the identifier too. */ - if (! TREE_PUBLIC (olddecl)) - TREE_PUBLIC (DECL_ASSEMBLER_NAME (olddecl)) = 0; - } - else + if (TREE_CODE (newdecl) != FUNCTION_DECL) TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); } else @@ -2464,7 +2449,20 @@ duplicate_decls (newdecl, olddecl) && TREE_READONLY (newdecl) && TREE_STATIC (newdecl) && ! DECL_THIS_EXTERN (newdecl)) TREE_PUBLIC (newdecl) = 0; + else if (TREE_CODE (newdecl) != FUNCTION_DECL) + TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); + } + + /* For functions, static overrides non-static. */ + if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); + /* This is since we don't automatically + copy the attributes of NEWDECL into OLDDECL. */ TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); + /* If this clears `static', clear it in the identifier too. */ + if (! TREE_PUBLIC (olddecl)) + TREE_PUBLIC (DECL_ASSEMBLER_NAME (olddecl)) = 0; } /* If either decl says `inline', this fn is inline, @@ -2854,7 +2852,8 @@ pushdecl (x) /* If new decl is `static' and an `extern' was seen previously, warn about it. */ - warn_extern_redeclared_static (x, t); + if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t)) + warn_extern_redeclared_static (x, t); } else { @@ -3964,20 +3963,13 @@ lookup_name_real (name, prefer_type, nonclass) done: if (val) { - /* Arbitrate between finding a TYPE_DECL and finding - other kinds of _DECLs. */ - if (TREE_CODE (val) == TYPE_DECL || prefer_type < 0) + if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template) + || TREE_CODE (val) == TYPE_DECL || prefer_type <= 0) return val; if (IDENTIFIER_HAS_TYPE_VALUE (name)) - { - register tree val_as_type = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name)); - - if (val == val_as_type || prefer_type > 0) - return val_as_type; + return TYPE_NAME (IDENTIFIER_TYPE_VALUE (name)); - return val; - } if (TREE_TYPE (val) == error_mark_node) return error_mark_node; } @@ -5312,7 +5304,9 @@ start_decl (declarator, declspecs, initialized, raises) default: /* Don't allow initializations for incomplete types except for arrays which might be completed by the initialization. */ - if (TYPE_SIZE (type) != NULL_TREE) + if (type == error_mark_node) + ; /* Don't complain again. */ + else if (TYPE_SIZE (type) != NULL_TREE) ; /* A complete type is ok. */ else if (TREE_CODE (type) != ARRAY_TYPE) { @@ -5768,7 +5762,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) TREE_TYPE (decl) = type = TREE_TYPE (init); DECL_INITIAL (decl) = init = NULL_TREE; } - if (IS_AGGR_TYPE (type) && DECL_NAME (decl)) + if (type != error_mark_node + && IS_AGGR_TYPE (type) && DECL_NAME (decl)) { if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type) cp_warning ("shadowing previous type declaration of `%#D'", decl); @@ -5856,7 +5851,7 @@ finish_decl (decl, init, asmspec_tree, need_pop) GNU_xref_decl (current_function_decl, decl); - if (TREE_CODE (decl) == FIELD_DECL || DECL_EXTERNAL (decl)) + if (TREE_CODE (decl) == FIELD_DECL) ; else if (TREE_CODE (decl) == CONST_DECL) { @@ -5960,6 +5955,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) DECL_INITIAL (decl) = error_mark_node; } } + else if (DECL_EXTERNAL (decl)) + ; else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't' && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type))) { @@ -6185,11 +6182,11 @@ finish_decl (decl, init, asmspec_tree, need_pop) store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0); TREE_ASM_WRITTEN (decl) = 1; } - else if (toplev) + else if (toplev && ! TREE_PUBLIC (decl)) { /* If this is a static const, change its apparent linkage if it belongs to a #pragma interface. */ - if (TREE_STATIC (decl) && !interface_unknown) + if (!interface_unknown) { TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = interface_only; @@ -6681,7 +6678,9 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, grokclassfn (ctype, declarator, decl, flags, quals); if (check) check_classfn (ctype, declarator, decl); - grok_ctor_properties (ctype, decl); + if (! grok_ctor_properties (ctype, decl)) + return NULL_TREE; + if (check == 0 && ! current_function_decl) { /* FIXME: this should only need to look at @@ -7393,18 +7392,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) { if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits)) { -#if 0 - if (pedantic) - pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); - else -#endif - if (longlong) - error ("`long long long' is too long for GCC"); + if (pedantic && flag_ansi) + pedwarn ("duplicate `long'"); + else if (longlong) + error ("`long long long' is too long for GCC"); else longlong = 1; } else if (RIDBIT_SETP (i, specbits)) - warning ("duplicate `%s'", IDENTIFIER_POINTER (id)); + pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); RIDBIT_SET (i, specbits); goto found; } @@ -7619,7 +7615,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) warning ("duplicate `volatile'"); virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits); - /* operators new and delete are implicitly static. */ if (RIDBIT_SETP (RID_STATIC, specbits)) staticp = 1 + (decl_context == FIELD); @@ -8049,8 +8044,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) else { if (flag_ansi) - cp_pedwarn ("ANSI C++ forbids variable-size array `%D'", - dname); + { + if (dname) + cp_pedwarn ("ANSI C++ forbids variable-size array `%D'", + dname); + else + cp_pedwarn ("ANSI C++ forbids variable-size array"); + } dont_grok_size: itype = build_binary_op (MINUS_EXPR, size, integer_one_node, 1); @@ -8070,8 +8070,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) type = build_cplus_array_type (type, itype); if (constp || volatilep) - /* Should this be c_build_type_variant? -jason */ - type = build_type_variant (type, constp, volatilep); + type = c_build_type_variant (type, constp, volatilep); ctype = NULL_TREE; } @@ -8383,9 +8382,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } } if (constp > 1) - warning ("duplicate `const'"); + pedwarn ("duplicate `const'"); if (volatilep > 1) - warning ("duplicate `volatile'"); + pedwarn ("duplicate `volatile'"); + if (TREE_CODE (declarator) == ADDR_EXPR + && (constp || volatilep)) + { + if (constp) + warning ("discarding `const' applied to a reference"); + if (volatilep) + warning ("discarding `volatile' applied to a reference"); + constp = volatilep = 0; + } } declarator = TREE_OPERAND (declarator, 0); ctype = NULL_TREE; @@ -8841,7 +8849,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ publicp = (RIDBIT_SETP (RID_EXTERN, specbits) - || (ctype != NULL_TREE && funcdef_flag >= 0) + || (ctype != NULL_TREE + && funcdef_flag >= 0 + && RIDBIT_NOTSETP (RID_INLINE, specbits)) || (friendp && ! funcdef_flag && RIDBIT_NOTSETP (RID_STATIC, specbits) @@ -8921,14 +8931,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (decl == NULL_TREE) { - /* ANSI C++ June 5 1992 WP 9.2.2 and 9.4.2. A member-declarator - cannot have an initializer, and a static member declaration must - be defined elsewhere. */ if (initialized) { + /* Motion 10 at San Diego: If a static const integral data + member is initialized with an integral constant + expression, the initializer may appear either in the + declaration (within the class), or in the definition, + but not both. If it appears in the class, the member is + a member constant. The file-scope definition is always + required. */ if (staticp) - error ("static member `%s' must be defined separately from its declaration", - IDENTIFIER_POINTER (declarator)); + { + if (pedantic) + { + if (! constp) + cp_pedwarn ("ANSI C++ forbids in-class initialization of non-const static member `%D'", + declarator); + + else if (! INTEGRAL_TYPE_P (type)) + cp_pedwarn ("ANSI C++ forbids member constant `%D' of non-integral type `%T'", declarator, type); + } + } + /* Note that initialization of const members is prohibited by the draft ANSI standard, though it appears to be in common practice. 12.6.2: The argument list is used to @@ -8936,9 +8960,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) initializer list) is the only way to initialize nonstatic const and reference members. */ else if (flag_ansi || ! constp) - pedwarn ("ANSI C++ forbids initialization of %s `%s'", - constp ? "const member" : "member", - IDENTIFIER_POINTER (declarator)); + cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'", + constp ? "const member" : "member", declarator); } if (staticp || (constp && initialized)) @@ -8952,7 +8975,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) TREE_STATIC (decl) = 1; /* In class context, static means public access. */ TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = !initialized; + DECL_EXTERNAL (decl) = !!staticp; } else { @@ -9472,7 +9495,7 @@ grokparms (first_parm, funcdef_flag) `grok_op_properties' takes notice of the various forms of operator= which are defined, as well as what sorts of type conversion may apply. Both functions take a FUNCTION_DECL as an argument. */ -void +int grok_ctor_properties (ctype, decl) tree ctype, decl; { @@ -9509,14 +9532,21 @@ grok_ctor_properties (ctype, decl) { if (TREE_CHAIN (parmtypes) != NULL_TREE && TREE_CHAIN (parmtypes) == void_list_node) - cp_error ("invalid constructor; you probably meant `%T (%T&)'", - ctype, ctype); - SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype); - TYPE_GETS_INIT_AGGR (ctype) = 1; + { + cp_error ("invalid constructor; you probably meant `%T (%T&)'", + ctype, ctype); + SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype); + + return 0; + } + else + TYPE_GETS_INIT_AGGR (ctype) = 1; } else if (TREE_CODE (parmtype) == VOID_TYPE || TREE_PURPOSE (parmtypes) != NULL_TREE) TYPE_HAS_DEFAULT_CONSTRUCTOR (ctype) = 1; + + return 1; } /* An operator with this name can be either unary or binary. */ @@ -9660,10 +9690,30 @@ grok_op_properties (decl, virtualp, friendp) || name == ansi_opname[(int) METHOD_CALL_EXPR]) return; /* no restrictions on args */ - if (IDENTIFIER_TYPENAME_P (name) - && TREE_CODE (TREE_TYPE (name)) == VOID_TYPE) - error ("void is not a valid type conversion operator"); - + if (IDENTIFIER_TYPENAME_P (name)) + { + tree t = TREE_TYPE (name); + if (TREE_CODE (t) == VOID_TYPE) + pedwarn ("void is not a valid type conversion operator"); + else if (! friendp) + { + int ref = (TREE_CODE (t) == REFERENCE_TYPE); + char *what = 0; + if (ref) + t = TYPE_MAIN_VARIANT (TREE_TYPE (t)); + + if (t == current_class_type) + what = "the same type"; + else if (IS_AGGR_TYPE (t) + && DERIVED_FROM_P (t, current_class_type)) + what = "a base class"; + + if (what) + warning ("conversion to %s%s will never use a type conversion operator", + ref ? "a reference to " : "", what); + } + } + if (name == ansi_opname[(int) MODIFY_EXPR]) { tree parmtype; @@ -9810,12 +9860,12 @@ xref_defn_tag (code_type_node, name, binfo) #endif #if 0 IDENTIFIER_LOCAL_VALUE (name) = - build_lang_decl (TYPE_DECL, ncp, NULL_TREE); + build_decl (TYPE_DECL, ncp, NULL_TREE); #endif rv = xref_tag (code_type_node, name, binfo, 0); if (! ANON_AGGRNAME_P (name)) { - register tree type_decl = build_lang_decl (TYPE_DECL, ncp, rv); + register tree type_decl = build_decl (TYPE_DECL, ncp, rv); #ifdef DWARF_DEBUGGING_INFO /* Mark the TYPE_DECL node created just above as a gratuitous one so that dwarfout.c will know not to generate a TAG_typedef DIE @@ -9875,10 +9925,10 @@ xref_tag (code_type_node, name, binfo, globalize) /* If a cross reference is requested, look up the type already defined for this tag and return it. */ - if ((t = IDENTIFIER_TYPE_VALUE(name))) - { - if (TREE_CODE(t) != code) t = NULL_TREE; - } + t = IDENTIFIER_TYPE_VALUE (name); + if (t && TREE_CODE (t) != code) + t = NULL_TREE; + if (xref_next_defn) { /* If we know we are defining this tag, only look it up in this scope @@ -10694,15 +10744,29 @@ start_function (declspecs, declarator, raises, pre_parsed_p) { TREE_PUBLIC (decl1) = 1; DECL_EXTERNAL (decl1) - = ((interface_only && !DECL_EXPLICITLY_INSTANTIATED (decl1)) + = (interface_only || (DECL_INLINE (decl1) && ! flag_implement_inlines)); } + else if (DECL_EXPLICIT_INSTANTIATION (decl1)) + { + TREE_PUBLIC (decl1) = 1; + DECL_EXTERNAL (decl1) = (DECL_INLINE (decl1) + && ! flag_implement_inlines); + } else - /* This is a definition, not a reference. - So normally clear DECL_EXTERNAL. - However, `extern inline' acts like a declaration except for - defining how to inline. So set DECL_EXTERNAL in that case. */ - DECL_EXTERNAL (decl1) = current_extern_inline; + { + /* This is a definition, not a reference. + So normally clear DECL_EXTERNAL. + However, `extern inline' acts like a declaration except for + defining how to inline. So set DECL_EXTERNAL in that case. */ + DECL_EXTERNAL (decl1) = current_extern_inline; + +#if 0 + DECL_DEFER_OUTPUT (decl1) + = (DECL_INLINE (decl1) && (DECL_IMPLICIT_INSTANTIATION (decl1) + || DECL_FUNCTION_MEMBER_P (decl1))); +#endif + } /* Record the decl so that the function name is defined. If we already have a decl for this name, and it is a FUNCTION_DECL, @@ -11703,6 +11767,9 @@ start_method (declspecs, declarator, raises) if (flag_default_inline) DECL_INLINE (fndecl) = 1; + if (processing_template_defn) + SET_DECL_IMPLICIT_INSTANTIATION (fndecl); + /* We read in the parameters on the maybepermanent_obstack, but we won't be getting back to them until after we may have clobbered them. So the call to preserve_data @@ -11726,7 +11793,10 @@ start_method (declspecs, declarator, raises) } if (DECL_CONSTRUCTOR_P (fndecl)) - grok_ctor_properties (current_class_type, fndecl); + { + if (! grok_ctor_properties (current_class_type, fndecl)) + return void_type_node; + } else if (IDENTIFIER_OPNAME_P (DECL_NAME (fndecl))) grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl), 0); } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 55414df..fa05063 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -116,6 +116,10 @@ int flag_external_templates = 0; int flag_alt_external_templates = 0; +/* Nonzero means that implicit instantiations will be emitted if needed. */ + +int flag_implicit_templates = 1; + /* Nonzero means warn about implicit declarations. */ int warn_implicit = 1; @@ -352,6 +356,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = {"nonnull-objects", &flag_assume_nonnull_objects, 1}, {"implement-inlines", &flag_implement_inlines, 1}, {"external-templates", &flag_external_templates, 1}, + {"implicit-templates", &flag_implicit_templates, 1}, {"huge-objects", &flag_huge_objects, 1}, {"conserve-space", &flag_conserve_space, 1}, {"vtable-thunks", &flag_vtable_thunks, 1}, @@ -1181,7 +1186,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree) value = grokdeclarator (declarator, declspecs, FIELD, init != 0, raises); if (! value) - return NULL_TREE; /* friends went bad. */ + return value; /* friend or constructor went bad. */ /* Pass friendly classes back. */ if (TREE_CODE (value) == VOID_TYPE) @@ -1236,21 +1241,13 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree) grok_function_init (value, init); init = NULL_TREE; } - else if (pedantic) - { -#if 0 - /* Already warned in grokdeclarator. */ - if (DECL_NAME (value)) - pedwarn ("ANSI C++ forbids initialization of member `%s'", - IDENTIFIER_POINTER (DECL_NAME (value))); - else - pedwarn ("ANSI C++ forbids initialization of fields"); -#endif - init = NULL_TREE; - } + else if (pedantic && ! TREE_STATIC (value)) + /* Already complained in grokdeclarator. */ + init = NULL_TREE; else { - /* We allow initializers to become parameters to base initializers. */ + /* We allow initializers to become parameters to base + initializers. */ if (TREE_CODE (init) == TREE_LIST) { if (TREE_CHAIN (init) == NULL_TREE) @@ -1352,8 +1349,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree) } if (TREE_CODE (value) == FUNCTION_DECL) { - /* grokdeclarator defers setting this. */ - TREE_PUBLIC (value) = 1; if (DECL_CHAIN (value) != NULL_TREE) { /* Need a fresh node here so that we don't get circularity @@ -1368,7 +1363,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree) if (DECL_FRIEND_P (value)) return void_type_node; - if (current_function_decl) + if (current_function_decl && ! IS_SIGNATURE (current_class_type)) cp_error ("method `%#D' of local class must be defined in class body", value); @@ -2345,7 +2340,8 @@ finish_vtable_vardecl (prev, vars) for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE; method = DECL_NEXT_METHOD (method)) { - if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method)) + if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method) + && !DECL_ABSTRACT_VIRTUAL_P (method)) { SET_CLASSTYPE_INTERFACE_KNOWN (ctype); CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method); @@ -2376,20 +2372,6 @@ finish_vtable_vardecl (prev, vars) mark_vtable_entries (vars); if (TREE_TYPE (DECL_INITIAL (vars)) == 0) store_init_value (vars, DECL_INITIAL (vars)); - if (flag_vtable_thunks) - { - tree list = CONSTRUCTOR_ELTS (DECL_INITIAL (vars)); - for (; list; list = TREE_CHAIN (list)) - { - tree vfunc = TREE_VALUE (list); - if (TREE_CODE (vfunc) == ADDR_EXPR) - { - vfunc = TREE_OPERAND (vfunc, 0); - if (TREE_CODE (vfunc) == THUNK_DECL) - emit_thunk (vfunc); - } - } - } #ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) @@ -2737,6 +2719,12 @@ finish_file () walk_vtables ((void (*)())0, finish_vtable_vardecl); + for (vars = getdecls (); vars; vars = TREE_CHAIN (vars)) + { + if (TREE_CODE (vars) == THUNK_DECL) + emit_thunk (vars); + } + /* Now write out inline functions which had their addresses taken and which were not declared virtual and which were not declared `extern inline'. */ @@ -2752,12 +2740,16 @@ finish_file () if (CLASSTYPE_INTERFACE_KNOWN (ctype)) { TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (ctype); + DECL_EXTERNAL (decl) + = (CLASSTYPE_INTERFACE_ONLY (ctype) + || (DECL_INLINE (decl) && ! flag_implement_inlines)); } } if (TREE_PUBLIC (decl) || TREE_ADDRESSABLE (decl)) { - if (DECL_EXTERNAL (decl)) + if (DECL_EXTERNAL (decl) + || (DECL_IMPLICIT_INSTANTIATION (decl) + && ! flag_implicit_templates)) assemble_external (decl); else { diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 6d2ec7f..f431f6a 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -837,25 +837,25 @@ dump_char (c) { switch (c) { - case '\n': + case TARGET_NEWLINE: OB_PUTS ("\\n"); break; - case '\t': + case TARGET_TAB: OB_PUTS ("\\t"); break; - case '\v': + case TARGET_VT: OB_PUTS ("\\v"); break; - case '\b': + case TARGET_BS: OB_PUTS ("\\b"); break; - case '\r': + case TARGET_CR: OB_PUTS ("\\r"); break; - case '\f': + case TARGET_FF: OB_PUTS ("\\f"); break; - case '\a': + case TARGET_BELL: OB_PUTS ("\\a"); break; case '\\': diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 1867414..084eebd 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1866,7 +1866,7 @@ build_member_call (cname, name, parmlist) { tree newtype = build_type_variant (type, TYPE_READONLY (oldtype), TYPE_VOLATILE (oldtype)); - decl = convert_force (TYPE_POINTER_TO (newtype), olddecl); + decl = convert_force (build_pointer_type (newtype), olddecl); } else decl = olddecl; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 595ba82..68f801e 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -1936,15 +1936,17 @@ default_assign_ref_body (bufp, lenp, type, fields) name = TYPE_NESTED_NAME (btype); s = IDENTIFIER_POINTER (name); - tneed = (2 * strlen (s)) + 33; + tneed = (2 * strlen (s)) + 42; if (tgot < tneed) { tgot = tneed; tbuf = (char *) alloca (tgot); } - sprintf (tbuf, "%s::operator=((%s%s&)_ctor_arg);", s, - TYPE_READONLY (type) ? "const " : "", s); + sprintf (tbuf, "%s::operator=((%s%s ::%s&)_ctor_arg);", s, + TYPE_READONLY (type) ? "const " : "", + CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct", + s); obstack_grow (&body, tbuf, strlen (tbuf)); } } @@ -2101,15 +2103,17 @@ default_copy_constructor_body (bufp, lenp, type, fields) name = TYPE_NESTED_NAME (btype); s = IDENTIFIER_POINTER (name); - tneed = (2 * strlen (s)) + 30; + tneed = (2 * strlen (s)) + 39; if (tgot < tneed) { tgot = tneed; tbuf = (char *) alloca (tgot); } - sprintf (tbuf, "%c%s((%s%s&)_ctor_arg)", sep, s, - TYPE_READONLY (type) ? "const " : "", s); + sprintf (tbuf, "%c%s((%s%s ::%s&)_ctor_arg)", sep, s, + TYPE_READONLY (type) ? "const " : "", + CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct", + s); sep = ','; obstack_grow (&prologue, tbuf, strlen (tbuf)); } diff --git a/gcc/cp/lex.h b/gcc/cp/lex.h index a9ea60e..3da4635 100644 --- a/gcc/cp/lex.h +++ b/gcc/cp/lex.h @@ -115,6 +115,7 @@ extern char *token_buffer; /* Pointer to token buffer. */ /* Back-door communication channel to the lexer. */ extern int looking_for_typename; +extern int looking_for_template; /* Tell the lexer where to look for names. */ extern tree got_scope; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index d0b847e..bdc040c 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -938,7 +938,9 @@ build_typename_overload (type) build_overload_name (type, 0, 1); id = get_identifier (obstack_base (&scratch_obstack)); IDENTIFIER_OPNAME_P (id) = 1; +#if 0 IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type); +#endif TREE_TYPE (id) = type; return id; } @@ -1676,8 +1678,9 @@ make_thunk (function, delta) int delta; { char buffer[250]; - tree thunk_fndecl; + tree thunk_fndecl, thunk_id; tree thunk; + char *func_name; static int thunk_number = 0; tree func_decl; if (TREE_CODE (function) != ADDR_EXPR) @@ -1685,14 +1688,26 @@ make_thunk (function, delta) func_decl = TREE_OPERAND (function, 0); if (TREE_CODE (func_decl) != FUNCTION_DECL) abort (); - sprintf (buffer, "__thunk_%d_%d", -delta, thunk_number++); - thunk = build_decl (THUNK_DECL, get_identifier (buffer), - TREE_TYPE (func_decl)); - DECL_RESULT (thunk) - = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type)); - make_function_rtl (thunk); - DECL_INITIAL (thunk) = function; - THUNK_DELTA (thunk) = delta; + func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl)); + sprintf (buffer, "__thunk_%d_%s", -delta, func_name); + thunk_id = get_identifier (buffer); + thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); + if (thunk && TREE_CODE (thunk) != THUNK_DECL) + { + error_with_decl ("implementation-reserved name `%s' used"); + IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE; + } + if (thunk == NULL_TREE) + { + thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl)); + DECL_RESULT (thunk) + = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type)); + make_function_rtl (thunk); + DECL_INITIAL (thunk) = function; + THUNK_DELTA (thunk) = delta; + /* So that finish_file can write out any thunks that need to be: */ + pushdecl_top_level (thunk); + } return thunk; } @@ -1725,6 +1740,19 @@ emit_thunk (thunk_fndecl) if (TREE_ASM_WRITTEN (thunk_fndecl)) return; + TREE_ASM_WRITTEN (thunk_fndecl) = 1; + + if (TREE_PUBLIC (function)) + { + TREE_PUBLIC (thunk_fndecl) = 1; + if (DECL_EXTERNAL (function)) + { + DECL_EXTERNAL (thunk_fndecl) = 1; + assemble_external (thunk_fndecl); + return; + } + } + decl_printable_name = thunk_printable_name; if (current_function_decl) abort (); @@ -1833,8 +1861,6 @@ emit_thunk (thunk_fndecl) expand_end_bindings (NULL, 1, 0); poplevel (0, 0, 0); - TREE_ASM_WRITTEN (thunk_fndecl) = 1; - /* From now on, allocate rtl in current_obstack, not in saveable_obstack. Note that that may have been done above, in save_for_inline_copying. The call to resume_temporary_allocation near the end of this function @@ -1848,10 +1874,6 @@ emit_thunk (thunk_fndecl) unshare_all_rtl (insns); - /* Instantiate all virtual registers. */ - - instantiate_virtual_regs (current_function_decl, get_insns ()); - /* We are no longer anticipating cse in this function, at least. */ cse_not_expected = 1; diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 30e076c..cb2046d 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -543,11 +543,12 @@ datadef: && TREE_PURPOSE (t) == NULL_TREE) { t = TREE_VALUE (t); - if (TREE_CODE (t) == RECORD_TYPE) + if (IS_AGGR_TYPE (t) + && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (t))) { if (CLASSTYPE_USE_TEMPLATE (t) == 0) - CLASSTYPE_USE_TEMPLATE (t) = 2; - else if (CLASSTYPE_USE_TEMPLATE (t) == 1) + SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t); + else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t)) error ("override declaration for already-expanded template"); } } @@ -2914,14 +2915,18 @@ absdcl: { $$ = make_pointer_declarator ($2, $3); } | '*' absdcl { $$ = make_pointer_declarator (NULL_TREE, $2); } - | '*' type_quals %prec EMPTY + | '*' nonempty_type_quals %prec EMPTY { $$ = make_pointer_declarator ($2, NULL_TREE); } + | '*' %prec EMPTY + { $$ = make_pointer_declarator (NULL_TREE, NULL_TREE); } | '&' nonempty_type_quals absdcl { $$ = make_reference_declarator ($2, $3); } | '&' absdcl { $$ = make_reference_declarator (NULL_TREE, $2); } - | '&' type_quals %prec EMPTY + | '&' nonempty_type_quals %prec EMPTY { $$ = make_reference_declarator ($2, NULL_TREE); } + | '&' %prec EMPTY + { $$ = make_reference_declarator (NULL_TREE, NULL_TREE); } | ptr_to_mem type_quals %prec EMPTY { tree arg = make_pointer_declarator ($2, NULL_TREE); $$ = build_parse_node (SCOPE_REF, $1, arg); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 997941c..36248be 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -116,7 +116,7 @@ process_template_parm (list, next) else { tree t = make_node (TEMPLATE_TYPE_PARM); - decl = build_lang_decl (TYPE_DECL, TREE_PURPOSE (parm), t); + decl = build_decl (TYPE_DECL, TREE_PURPOSE (parm), t); TYPE_NAME (t) = decl; TREE_VALUE (parm) = t; } @@ -581,7 +581,7 @@ lookup_template_class (d1, arglist, in_decl) tree t = make_lang_type (UNINSTANTIATED_P_TYPE); tree d; id = make_anon_name (); - d = build_lang_decl (TYPE_DECL, id, t); + d = build_decl (TYPE_DECL, id, t); TYPE_NAME (t) = d; TYPE_VALUES (t) = build_tree_list (template, arglist); pushdecl_top_level (d); @@ -635,7 +635,7 @@ push_template_decls (parmlist, arglist, class_level) } decl = arg; my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273); - decl = build_lang_decl (TYPE_DECL, parm, decl); + decl = build_decl (TYPE_DECL, parm, decl); } else { @@ -987,7 +987,7 @@ instantiate_class_template (classname, setup_parse) if (!TREE_TYPE (classname)) { tree t = make_lang_type (RECORD_TYPE); - tree d = build_lang_decl (TYPE_DECL, classname, t); + tree d = build_decl (TYPE_DECL, classname, t); DECL_NAME (d) = classname; TYPE_NAME (t) = d; pushdecl (d); @@ -1320,7 +1320,7 @@ tsubst (t, args, nargs, in_decl) tree decls; int got_it = 0; - decls = lookup_name (r, 0); + decls = lookup_name_nonclass (r); if (decls == NULL_TREE) /* no match */; else if (TREE_CODE (decls) == TREE_LIST) @@ -1645,11 +1645,18 @@ instantiate_template (tmpl, targ_ptr) DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); } + t = DECL_TEMPLATE_INFO (tmpl); + /* If we have a preexisting version of this function, don't expand the template version, use the other instead. */ - t = DECL_TEMPLATE_INFO (tmpl); - if (t->text && !(DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl))) + if (DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl)) { + SET_DECL_TEMPLATE_SPECIALIZATION (fndecl); + p = (struct pending_inline *)0; + } + else if (t->text) + { + SET_DECL_IMPLICIT_INSTANTIATION (fndecl); p = (struct pending_inline *) permalloc (sizeof (struct pending_inline)); p->parm_vec = t->parm_vec; p->bindings = targs; @@ -1819,7 +1826,7 @@ end_template_instantiation (name) my_friendly_assert (t != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (t)) == 't', 287); - CLASSTYPE_USE_TEMPLATE (t) = 2; + SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t); /* Make methods of template classes static, unless -fexternal-templates is given. */ if (!flag_external_templates) @@ -2227,8 +2234,10 @@ do_pending_expansions () if (TREE_ASM_WRITTEN (t)) DECIDE (0); - if (DECL_EXPLICITLY_INSTANTIATED (t)) + if (DECL_EXPLICIT_INSTANTIATION (t)) DECIDE (1); + else if (! flag_implicit_templates) + DECIDE (0); /* If it's a method, let the class type decide it. @@ What if the method template is in a separate file? @@ -2357,7 +2366,12 @@ do_function_instantiation (declspecs, declarator) if (! result) cp_error ("no matching template for `%D' found", decl); - DECL_EXPLICITLY_INSTANTIATED (result) = 1; + if (flag_external_templates) + return; + + SET_DECL_EXPLICIT_INSTANTIATION (result); + TREE_PUBLIC (result) = 1; + DECL_EXTERNAL (result) = DECL_INLINE (result) && ! flag_implement_inlines; } void @@ -2366,14 +2380,24 @@ do_type_instantiation (name) { tree t = TREE_TYPE (name); - CLASSTYPE_EXPLICITLY_INSTANTIATED (t) = 1; + if (flag_external_templates) + return; + + SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t); CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 1; + SET_CLASSTYPE_INTERFACE_KNOWN (t); + CLASSTYPE_INTERFACE_ONLY (t) = 0; /* this should really be done by instantiate_member_templates */ { tree method = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); for (; method; method = TREE_CHAIN (method)) - DECL_EXPLICITLY_INSTANTIATED (method) = 1; + { + SET_DECL_EXPLICIT_INSTANTIATION (method); + TREE_PUBLIC (method) = 1; + DECL_EXTERNAL (method) = (DECL_INLINE (method) + && ! flag_implement_inlines); + } } /* and data member templates, too */ @@ -2384,7 +2408,7 @@ create_nested_upt (scope, name) tree scope, name; { tree t = make_lang_type (UNINSTANTIATED_P_TYPE); - tree d = build_lang_decl (TYPE_DECL, name, t); + tree d = build_decl (TYPE_DECL, name, t); TYPE_NAME (t) = d; TYPE_VALUES (t) = TYPE_VALUES (scope); diff --git a/gcc/cp/sig.c b/gcc/cp/sig.c index 979d7aa..cd2eead 100644 --- a/gcc/cp/sig.c +++ b/gcc/cp/sig.c @@ -512,8 +512,8 @@ build_signature_table_constructor (sig_ty, rhs) { if (! IS_DEFAULT_IMPLEMENTATION (sig_method)) { - cp_error ("class `%T' does not contain method `%s'", - rhstype, (int) IDENTIFIER_POINTER (sig_mname)); + cp_error ("class `%T' does not contain method `%D'", + rhstype, sig_mname); undo_casts (sig_ty); return error_mark_node; } diff --git a/gcc/cp/spew.c b/gcc/cp/spew.c index e85be53..ea00ba2 100644 --- a/gcc/cp/spew.c +++ b/gcc/cp/spew.c @@ -236,6 +236,7 @@ probe_obstack (h, obj, nlevels) a typename (when it may be a local variable or a class variable). Value is 0 if we treat this name in a default fashion. */ extern int looking_for_typename; +int looking_for_template; extern struct obstack *current_obstack, *saveable_obstack; tree got_scope; @@ -298,6 +299,8 @@ yylex() if (nth_token (1)->yychar == SCOPE) /* Don't interfere with the setting from an 'aggr' prefix. */ looking_for_typename++; + else if (nth_token (1)->yychar == '<') + looking_for_template = 1; trrr = lookup_name (tmp_token.yylval.ttype, -2); @@ -334,6 +337,7 @@ yylex() consume_token (); if (looking_for_typename > 0) looking_for_typename--; + looking_for_template = 0; break; case SCSPEC: diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index b4712a6..98cbd41 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -860,7 +860,7 @@ list_hash_add (hashcode, list) This function frees the list you pass in if it is a duplicate. */ /* Set to 1 to debug without canonicalization. Never set by program. */ -int debug_no_list_hash = 0; +static int debug_no_list_hash = 0; tree list_hash_canon (hashcode, list) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index f2b375b..ffc6fd7 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -542,7 +542,9 @@ comp_array_types (cmp, t1, t2, strict) 2 : strict, except that if one type is a reference and the other is not, compare the target type of the reference to the type that's not a reference (ARM, p308). + This is used for checking for illegal overloading. 1 : strict (compared according to ANSI C) + This is used for checking whether two function decls match. 0 : <= (compared according to C++) -1: <= or >= (relaxed) @@ -608,7 +610,7 @@ comptypes (type1, type2, strict) if (TYPE_READONLY (t1) != TYPE_READONLY (t2)) return 0; - if (TREE_THIS_VOLATILE (t1) != TREE_THIS_VOLATILE (t2)) + if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2)) return 0; /* Allow for two different type nodes which have essentially the same @@ -739,7 +741,13 @@ comp_target_types (ttl, ttr, nptrs) return 0; if (TREE_CODE (ttr) == POINTER_TYPE) - return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs - 1); + { + if (TREE_CODE (TREE_TYPE (ttl)) == POINTER_TYPE + || TREE_CODE (TREE_TYPE (ttl)) == ARRAY_TYPE) + return comp_ptr_ttypes (TREE_TYPE (ttl), TREE_TYPE (ttr)); + else + return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs - 1); + } if (TREE_CODE (ttr) == REFERENCE_TYPE) return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs); @@ -2425,12 +2433,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) called_thing = "constructor"; else called_thing = "member function"; - i -= 1; } else - { - called_thing = "function"; - } + called_thing = "function"; } for (valtail = values, typetail = typelist; @@ -2510,7 +2515,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */ if (TREE_CODE (val) == NOP_EXPR - && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0))) + && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)) + && (type == 0 || TREE_CODE (type) != REFERENCE_TYPE)) val = TREE_OPERAND (val, 0); if ((type == 0 || TREE_CODE (type) != REFERENCE_TYPE) @@ -2886,6 +2892,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) { + if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) + { + error ("division by zero"); + op1 = integer_one_node; + } + else if (TREE_CODE (op1) == REAL_CST && real_zerop (op1)) + { + error ("division by zero"); + op1 = build_real (TREE_TYPE (op1), dconst1); + } + if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)) resultcode = RDIV_EXPR; else @@ -2936,6 +2953,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: + if (code1 == INTEGER_TYPE && integer_zerop (op1)) + { + error ("division by zero"); + op1 = integer_one_node; + } + else if (code1 == REAL_TYPE && real_zerop (op1)) + { + error ("division by zero"); + op1 = build_real (TREE_TYPE (op1), dconst1); + } + if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { /* Although it would be tempting to shorten always here, that loses @@ -4001,17 +4029,15 @@ build_unary_op (code, xarg, noconvert) TREE_REFERENCE_EXPR (arg) = 1; return arg; } - else if (TREE_CODE (arg) == FUNCTION_DECL + else if (pedantic + && TREE_CODE (arg) == FUNCTION_DECL && DECL_NAME (arg) && DECL_CONTEXT (arg) == NULL_TREE && IDENTIFIER_LENGTH (DECL_NAME (arg)) == 4 && IDENTIFIER_POINTER (DECL_NAME (arg))[0] == 'm' && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (arg)), "main")) - { - /* ARM $3.4 */ - error ("attempt to take address of function `main'"); - return error_mark_node; - } + /* ARM $3.4 */ + pedwarn ("taking address of function `main'"); /* Let &* cancel out to simplify resulting code. */ if (TREE_CODE (arg) == INDIRECT_REF) @@ -4911,6 +4937,13 @@ build_c_cast (type, expr) } } + if (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) + { + cp_error ("casting to function type `%T'", type); + return error_mark_node; + } + if (IS_SIGNATURE (type)) { error ("cast specifies signature type"); @@ -5396,6 +5429,33 @@ build_modify_expr (lhs, modifycode, rhs) } } + if (TREE_CODE (lhs) == OFFSET_REF) + { + if (TREE_OPERAND (lhs, 0) == NULL_TREE) + { + /* Static class member? */ + tree member = TREE_OPERAND (lhs, 1); + if (TREE_CODE (member) == VAR_DECL) + lhs = member; + else + { + compiler_error ("invalid static class member"); + return error_mark_node; + } + } + else + lhs = resolve_offset_ref (lhs); + + olhstype = lhstype = TREE_TYPE (lhs); + } + + if (TREE_CODE (lhstype) == REFERENCE_TYPE + && modifycode != INIT_EXPR) + { + lhs = convert_from_reference (lhs); + olhstype = lhstype = TREE_TYPE (lhs); + } + /* If a binary op has been requested, combine the old LHS value with the RHS producing the value we should actually store into the LHS. */ @@ -5413,9 +5473,6 @@ build_modify_expr (lhs, modifycode, rhs) } else if (modifycode == NOP_EXPR) { - /* must deal with overloading of `operator=' here. */ - if (TREE_CODE (lhstype) == REFERENCE_TYPE) - lhstype = TREE_TYPE (lhstype); #if 1 /* `operator=' is not an inheritable operator. */ if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_HAS_ASSIGNMENT (lhstype)) @@ -5490,7 +5547,6 @@ build_modify_expr (lhs, modifycode, rhs) newrhs = build_binary_op (modifycode, lhs, rhs, 1); } -#if 0 /* Handle a cast used as an "lvalue". We have already performed any binary operator using the value as cast. Now convert the result to the cast type of the lhs, @@ -5515,6 +5571,9 @@ build_modify_expr (lhs, modifycode, rhs) { tree inner_lhs = TREE_OPERAND (lhs, 0); tree result; + if (! lvalue_p (lhs) && pedantic) + pedwarn ("cast to non-reference type used as lvalue"); + result = build_modify_expr (inner_lhs, NOP_EXPR, convert (TREE_TYPE (inner_lhs), convert (lhstype, newrhs))); @@ -5523,25 +5582,6 @@ build_modify_expr (lhs, modifycode, rhs) return convert_force (TREE_TYPE (lhs), result); } } -#endif - - if (TREE_CODE (lhs) == OFFSET_REF) - { - if (TREE_OPERAND (lhs, 0) == NULL_TREE) - { - /* Static class member? */ - tree member = TREE_OPERAND (lhs, 1); - if (TREE_CODE (member) == VAR_DECL) - lhs = member; - else - { - compiler_error ("invalid static class member"); - return error_mark_node; - } - } - else - lhs = resolve_offset_ref (lhs); - } /* Now we have handled acceptable kinds of LHS that are not truly lvalues. Reject anything strange now. */ @@ -5576,7 +5616,18 @@ build_modify_expr (lhs, modifycode, rhs) && (TREE_CODE (lhstype) == INTEGER_TYPE || TREE_CODE (lhstype) == REAL_TYPE || TREE_CODE (lhstype) == ENUMERAL_TYPE)) - lhstype = TREE_TYPE (get_unwidened (lhs, 0)); + { + lhstype = TREE_TYPE (get_unwidened (lhs, 0)); + + /* If storing in a field that is in actuality a short or narrower + than one, we must store in the field in its actual type. */ + + if (lhstype != TREE_TYPE (lhs)) + { + lhs = copy_node (lhs); + TREE_TYPE (lhs) = lhstype; + } + } /* check to see if there is an assignment to `this' */ if (lhs == current_class_decl) @@ -5734,15 +5785,6 @@ build_modify_expr (lhs, modifycode, rhs) #endif } - /* If storing in a field that is in actuality a short or narrower than one, - we must store in the field in its actual type. */ - - if (lhstype != TREE_TYPE (lhs)) - { - lhs = copy_node (lhs); - TREE_TYPE (lhs) = lhstype; - } - /* Convert new value to destination type. */ if (TREE_CODE (lhstype) == ARRAY_TYPE) @@ -6081,6 +6123,14 @@ build_ptrmemfunc (type, pfn, force) return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0); } + if (TREE_CODE (pfn) == TREE_LIST) + { + pfn = instantiate_type (type, pfn, 1); + if (pfn == error_mark_node) + return error_mark_node; + pfn = build_unary_op (ADDR_EXPR, pfn, 0); + } + /* Allow pointer to member conversions here. */ delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))), TYPE_METHOD_BASETYPE (TREE_TYPE (type)), @@ -6399,45 +6449,63 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) } else { - int const_parity = TYPE_READONLY (type) ^ TYPE_READONLY (rhstype); - int volatile_parity = TYPE_VOLATILE (type) ^ TYPE_VOLATILE (rhstype); + int add_quals = 0, const_parity = 0, volatile_parity = 0; + int left_const = 1; int unsigned_parity; int nptrs = 0; - while (TREE_CODE (ttl) == POINTER_TYPE - && TREE_CODE (ttr) == POINTER_TYPE) + /* This code is basically a duplicate of comp_ptr_ttypes_real. */ + for (; ; ttl = TREE_TYPE (ttl), ttr = TREE_TYPE (ttr)) { nptrs -= 1; - const_parity |= TYPE_READONLY (ttl) ^ TYPE_READONLY (ttr); - volatile_parity |= TYPE_VOLATILE (ttl) ^ TYPE_VOLATILE (ttr); - ttl = TREE_TYPE (ttl); - ttr = TREE_TYPE (ttr); + const_parity |= TYPE_READONLY (ttl) < TYPE_READONLY (ttr); + volatile_parity |= TYPE_VOLATILE (ttl) < TYPE_VOLATILE (ttr); + + if (! left_const + && (TYPE_READONLY (ttl) > TYPE_READONLY (ttr) + || TYPE_VOLATILE (ttl) > TYPE_VOLATILE (ttr))) + add_quals = 1; + left_const &= TYPE_READONLY (ttl); + + if (TREE_CODE (ttl) != POINTER_TYPE) + break; } unsigned_parity = TREE_UNSIGNED (ttl) - TREE_UNSIGNED (ttr); if (unsigned_parity) - if (TREE_UNSIGNED (ttl)) - ttr = unsigned_type (ttr); - else - ttl = unsigned_type (ttl); + { + if (TREE_UNSIGNED (ttl)) + ttr = unsigned_type (ttr); + else + ttl = unsigned_type (ttl); + } if (comp_target_types (ttl, ttr, nptrs)) { + if (add_quals) + { + if (fndecl) + cp_pedwarn ("passing `%T' as argument %P of `%D' adds cv-quals without intervening `const'", + rhstype, parmnum, fndecl); + else + cp_pedwarn ("%s to `%T' from `%T' adds cv-quals without intervening `const'", + errtype, type, rhstype); + } if (const_parity) { if (fndecl) - cp_warning ("passing `%T' as argument %P of `%D' discards const", + cp_pedwarn ("passing `%T' as argument %P of `%D' discards const", rhstype, parmnum, fndecl); else - cp_warning ("%s to `%T' from `%T' discards const", + cp_pedwarn ("%s to `%T' from `%T' discards const", errtype, type, rhstype); } if (volatile_parity) { if (fndecl) - cp_warning ("passing `%T' as argument %P of `%D' discards volatile", + cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile", rhstype, parmnum, fndecl); else - cp_warning ("%s to `%T' from `%T' discards volatile", + cp_pedwarn ("%s to `%T' from `%T' discards volatile", errtype, type, rhstype); } if (unsigned_parity > 0) @@ -6591,7 +6659,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs, since RHS is used in non-lvalue context. */ if (TREE_CODE (rhs) == NOP_EXPR - && TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0))) + && TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0)) + && codel != REFERENCE_TYPE) rhs = TREE_OPERAND (rhs, 0); if (rhs == error_mark_node @@ -7143,3 +7212,40 @@ c_expand_start_case (exp) return exp; } + +/* CONSTP remembers whether or not all the intervening pointers in the `to' + type have been const. */ +int +comp_ptr_ttypes_real (to, from, constp) + tree to, from; + int constp; +{ + for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) + { + if (TREE_CODE (to) != TREE_CODE (from)) + return 0; + + if (TYPE_READONLY (from) > TYPE_READONLY (to) + || TYPE_VOLATILE (from) > TYPE_VOLATILE (to)) + return 0; + + if (! constp + && (TYPE_READONLY (to) > TYPE_READONLY (from) + || TYPE_VOLATILE (to) > TYPE_READONLY (from))) + return 0; + constp &= TYPE_READONLY (to); + + if (TREE_CODE (to) != POINTER_TYPE) + return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1); + } +} + +/* When comparing, say, char ** to char const **, this function takes the + 'char *' and 'char const *'. Do not pass non-pointer types to this + function. */ +int +comp_ptr_ttypes (to, from) + tree to, from; +{ + return comp_ptr_ttypes_real (to, from, 1); +} diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index baf55a4..237d02a 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -655,6 +655,7 @@ digest_init (type, init, tail) && ((TREE_CODE (init) == ADDR_EXPR && TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE) + || TREE_CODE (init) == TREE_LIST || integer_zerop (init) || (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init))))) { @@ -1237,6 +1238,12 @@ build_x_arrow (datum) if (type == error_mark_node) return error_mark_node; + if (TREE_CODE (rval) == OFFSET_REF) + { + rval = resolve_offset_ref (datum); + type = TREE_TYPE (rval); + } + if (TREE_CODE (type) == REFERENCE_TYPE) { rval = convert_from_reference (rval); @@ -1268,7 +1275,6 @@ build_x_arrow (datum) else last_rval = default_conversion (rval); - more: /* Signature pointers are not dereferenced. */ if (TYPE_LANG_SPECIFIC (TREE_TYPE (last_rval)) && IS_SIGNATURE_POINTER (TREE_TYPE (last_rval))) @@ -1277,20 +1283,6 @@ build_x_arrow (datum) if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE) return build_indirect_ref (last_rval, NULL_PTR); - if (TREE_CODE (TREE_TYPE (last_rval)) == OFFSET_TYPE) - { - if (TREE_CODE (last_rval) == OFFSET_REF - && TREE_STATIC (TREE_OPERAND (last_rval, 1))) - { - last_rval = TREE_OPERAND (last_rval, 1); - if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE) - last_rval = convert_from_reference (last_rval); - goto more; - } - compiler_error ("invalid member type in build_x_arrow"); - return error_mark_node; - } - if (types_memoized) error ("result of `operator->()' yields non-pointer result"); else @@ -1372,7 +1364,6 @@ build_functional_cast (exp, parms) or a C cast in C++'s `functional' notation. */ tree type, name = NULL_TREE; tree expr_as_ctor = NULL_TREE; - tree expr_as_conversion = NULL_TREE; if (exp == error_mark_node || parms == error_mark_node) return error_mark_node; @@ -1423,7 +1414,12 @@ build_functional_cast (exp, parms) /* this must build a C cast */ if (parms == NULL_TREE) return build1 (NOP_EXPR, type, integer_zero_node); - return build_c_cast (type, build_compound_expr (parms)); + else if (TREE_CHAIN (parms) != NULL_TREE) + { + pedwarn ("initializer list being treated as compound expression"); + parms = build_compound_expr (parms); + } + return build_c_cast (type, parms); } if (TYPE_SIZE (type) == NULL_TREE) @@ -1433,90 +1429,45 @@ build_functional_cast (exp, parms) } if (parms && TREE_CHAIN (parms) == NULL_TREE) - expr_as_conversion - = build_type_conversion (CONVERT_EXPR, type, TREE_VALUE (parms), 0); - - if (! TYPE_HAS_CONSTRUCTOR (type) && parms != NULL_TREE) - { - char *msg = 0; + return build_c_cast (type, parms); - if (parms == NULL_TREE) - msg = "argument missing in cast to `%T' type"; - else if (TREE_CHAIN (parms) == NULL_TREE) - { - if (expr_as_conversion == NULL_TREE) - msg = "conversion to type `%T' failed"; - } - else msg = "type `%T' does not have a constructor"; + expr_as_ctor = build_method_call (NULL_TREE, name, parms, + NULL_TREE, LOOKUP_NORMAL); - if (expr_as_conversion) - return expr_as_conversion; + if (expr_as_ctor == error_mark_node) + return error_mark_node; - cp_error (msg, type); - return error_mark_node; - } + if (current_function_decl) + return build_cplus_new (type, expr_as_ctor, 0); { - int flags = LOOKUP_SPECULATIVELY|LOOKUP_NORMAL; - - if (parms && TREE_CHAIN (parms) == NULL_TREE) - flags |= LOOKUP_NO_CONVERSION; + register tree parm = TREE_OPERAND (expr_as_ctor, 1); - expr_as_ctor = build_method_call (NULL_TREE, name, parms, - NULL_TREE, flags); - - if (expr_as_ctor == error_mark_node) - return error_mark_node; - - else if (expr_as_ctor) - { - if (expr_as_conversion && expr_as_conversion != error_mark_node) - { - /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */ - cp_error ("ambiguity between conversion to `%T' and constructor", - type); - return error_mark_node; - } - - if (current_function_decl) - return build_cplus_new (type, expr_as_ctor, 0); - - { - register tree parm = TREE_OPERAND (expr_as_ctor, 1); - - /* Initializers for static variables and parameters have - to handle doing the initialization and cleanup themselves. */ - my_friendly_assert (TREE_CODE (expr_as_ctor) == CALL_EXPR, 322); + /* Initializers for static variables and parameters have + to handle doing the initialization and cleanup themselves. */ + my_friendly_assert (TREE_CODE (expr_as_ctor) == CALL_EXPR, 322); #if 0 - /* The following assertion fails in cases where we are initializing - a static member variable of a particular instance of a template - class with a call to a constructor of the given instance, as in: - - TMPL<int> object = TMPL<int>(); - - Curiously, the assertion does not fail if we do the same thing - for a static member of a non-template class, as in: - - T object = T(); - - I can't see why we should care here whether or not the initializer - expression involves a call to `new', so for the time being, it - seems best to just avoid doing this assertion. */ - my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)), 323); + /* The following assertion fails in cases where we are initializing + a static member variable of a particular instance of a template + class with a call to a constructor of the given instance, as in: + + TMPL<int> object = TMPL<int>(); + + Curiously, the assertion does not fail if we do the same thing + for a static member of a non-template class, as in: + + T object = T(); + + I can't see why we should care here whether or not the initializer + expression involves a call to `new', so for the time being, it + seems best to just avoid doing this assertion. */ + my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)), 323); #endif - TREE_VALUE (parm) = NULL_TREE; - expr_as_ctor = build_indirect_ref (expr_as_ctor, NULL_PTR); - TREE_HAS_CONSTRUCTOR (expr_as_ctor) = 1; - } - return expr_as_ctor; - } - - if (expr_as_conversion) - return expr_as_conversion; - - cp_error ("no suitable conversion to `%T' exists", type); - return error_mark_node; + TREE_VALUE (parm) = NULL_TREE; + expr_as_ctor = build_indirect_ref (expr_as_ctor, NULL_PTR); + TREE_HAS_CONSTRUCTOR (expr_as_ctor) = 1; } + return expr_as_ctor; } /* Return the character string for the name that encodes the |