OSDN Git Service

39th Cygnus<->FSF merge
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Jun 1994 21:42:31 +0000 (21:42 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Jun 1994 21:42:31 +0000 (21:42 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@7439 138bc75d-0d04-0410-961f-82ee72b054a4

21 files changed:
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/Makefile.in
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/lex.h
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/sig.c
gcc/cp/spew.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c

index f4b1424..385d239 100644 (file)
@@ -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.
index 0bf1b78..b888289 100644 (file)
@@ -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++
+
+\f
 # 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)
 \f
 # Clean hooks:
index 120e330..231d1a3 100644 (file)
@@ -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
 
index e957776..6d2b26c 100644 (file)
@@ -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++;
            }
        }
index 4fab523..638fedf 100644 (file)
@@ -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;
 
index 061c7f1..7ae511f 100644 (file)
@@ -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)
 \f
 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));
index 7bfe802..fc8d261 100644 (file)
@@ -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)
index fd73388..10e9d0e 100644 (file)
@@ -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);
     }
index 55414df..fa05063 100644 (file)
@@ -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
            {   
index 6d2ec7f..f431f6a 100644 (file)
@@ -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 '\\':
index 1867414..084eebd 100644 (file)
@@ -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;
index 595ba82..68f801e 100644 (file)
@@ -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));
        }
index a9ea60e..3da4635 100644 (file)
@@ -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;
index d0b847e..bdc040c 100644 (file)
@@ -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;
index 30e076c..cb2046d 100644 (file)
@@ -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);
index 997941c..36248be 100644 (file)
@@ -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);
index 979d7aa..cd2eead 100644 (file)
@@ -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;
            }
index e85be53..ea00ba2 100644 (file)
@@ -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:
index b4712a6..98cbd41 100644 (file)
@@ -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)
index f2b375b..ffc6fd7 100644 (file)
@@ -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);
+}
index baf55a4..237d02a 100644 (file)
@@ -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;
 }
 \f
 /* Return the character string for the name that encodes the