OSDN Git Service

86th Cygnus<->FSF quick merge
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 24 Apr 1996 18:30:21 +0000 (18:30 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 24 Apr 1996 18:30:21 +0000 (18:30 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@11877 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/Makefile.in
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/rtti.c
gcc/cp/tree.c
gcc/cp/typeck.c

index 44e3469..b455ae8 100644 (file)
@@ -1,3 +1,47 @@
+Wed Apr 24 00:36:21 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (tsubst_expr, DECL_STMT): If we don't have an initializer,
+       don't pass LOOKUP_ONLYCONVERTING.
+
+Tue Apr 23 17:18:47 1996  Bob Manson  <manson@charmed.cygnus.com>
+
+       * typeck.c (common_type): Fix the ARRAY_TYPE case so it
+       properly keeps track of const and volatile type modifiers.
+
+Tue Apr 23 10:52:56 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * tree.c (cp_tree_equal): C++ version of simple_cst_equal.
+       * pt.c (comp_template_args): Use it.
+
+       * rtti.c (get_tinfo_fn, build_dynamic_cast, expand_*_desc): Call
+       assemble_external for artificial function decls.
+
+       * decl.c (cp_finish_decl): Oops.
+
+Mon Apr 22 17:28:27 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl2.c (import_export_decl): Put static data member templates
+       into common storage, or make them weak, depending on whether they
+       are dynamically or statically initialized.
+       (get_sentry): New function.
+       (finish_file): Do import_export_decl for static data members before
+       building the init/fini functions.  Don't init/fini a variable that's
+       EXTERNAL.  Use a sentry for variables in common.  Fix mismatching
+       push/pop_temp_slots.
+       * decl.c (cp_finish_decl): If DECL_NOT_REALLY_EXTERN, do the
+       expand_static_init thang.
+       * method.c (get_id_2): New function.
+
+Mon Apr 22 15:32:45 1996  Bob Manson  <manson@charmed.cygnus.com>
+
+       * parse.y (empty_parms): Make sure we use C++-style prototypes
+       when we're declaring member functions.
+
+Sun Apr 21 10:08:22 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * Makefile.in (CONFLICTS): 16 s/r conflicts.
+       * parse.y (self_template_type): New nonterminal.
+
 Thu Apr 18 08:56:54 1996  Jason Merrill  <jason@yorick.cygnus.com>
 
        * decl.c (make_typename_type): Handle getting a TYPE_DECL for a
index 37ccc18..fe9ef8d 100644 (file)
@@ -195,7 +195,7 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h
        $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
   `echo $(PARSE_C) | sed 's,^\./,,'`
 
-CONFLICTS = expect 12 shift/reduce conflicts and 39 reduce/reduce conflicts.
+CONFLICTS = expect 16 shift/reduce conflicts and 39 reduce/reduce conflicts.
 $(PARSE_H) : $(PARSE_C)
 $(PARSE_C) : $(srcdir)/parse.y
        @echo $(CONFLICTS)
index da41eed..a4b8c80 100644 (file)
@@ -6567,7 +6567,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
 
       if (TREE_CODE (decl) == FUNCTION_DECL)
        ;
-      else if (DECL_EXTERNAL (decl))
+      else if (DECL_EXTERNAL (decl)
+              && ! (DECL_LANG_SPECIFIC (decl)
+                    && DECL_NOT_REALLY_EXTERN (decl)))
        {
          if (init)
            DECL_INITIAL (decl) = init;
index fe32649..5c9cf35 100644 (file)
@@ -2729,7 +2729,6 @@ import_export_decl (decl)
       DECL_NOT_REALLY_EXTERN (decl) = 1;
       if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
        {
-         /* For now, leave vars public so multiple defs will break.  */
          if (TREE_CODE (decl) == FUNCTION_DECL)
            {
              if (flag_weak)
@@ -2737,6 +2736,19 @@ import_export_decl (decl)
              else
                TREE_PUBLIC (decl) = 0;
            }
+         /* Dynamically initialized vars go into common.  */
+         else if (DECL_INITIAL (decl) == NULL_TREE
+                  || DECL_INITIAL (decl) == error_mark_node)
+           DECL_COMMON (decl) = 1;
+         else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
+           {
+             DECL_COMMON (decl) = 1;
+             DECL_INITIAL (decl) = error_mark_node;
+           }
+         /* Statically initialized vars are weak or comdat, if supported.  */
+         else if (flag_weak)
+           DECL_WEAK (decl) = 1;
+         /* else leave vars public so multiple defs will break.  */
        }
       else
        DECL_NOT_REALLY_EXTERN (decl) = 0;
@@ -2808,6 +2820,31 @@ extern tree pending_templates;
 #define TIMEVAR(VAR, BODY)    \
 do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
 
+extern struct obstack permanent_obstack;
+extern tree get_id_2 ();
+
+tree
+get_sentry (base)
+     tree base;
+{
+  tree sname = get_id_2 ("__sn", base);
+  tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
+  if (! sentry)
+    {
+      push_obstacks (&permanent_obstack, &permanent_obstack);
+      sentry = build_decl (VAR_DECL, sname, integer_type_node);
+      TREE_PUBLIC (sentry) = 1;
+      DECL_ARTIFICIAL (sentry) = 1;
+      TREE_STATIC (sentry) = 1;
+      TREE_USED (sentry) = 1;
+      DECL_COMMON (sentry) = 1;
+      pushdecl_top_level (sentry);
+      cp_finish_decl (sentry, NULL_TREE, NULL_TREE, 0, 0);
+      pop_obstacks ();
+    }
+  return sentry;
+}
+
 /* This routine is called from the last rule in yyparse ().
    Its job is to create all the code needed to initialize and
    destroy the global aggregates.  We do the destruction
@@ -2880,6 +2917,18 @@ finish_file ()
      that we can pick up any other tdecls that those routines need. */
   walk_vtables ((void (*)())0, finish_prevtable_vardecl);
 
+  for (vars = pending_statics; vars; vars = TREE_CHAIN (vars))
+    {
+      tree decl = TREE_VALUE (vars);
+
+      if (DECL_TEMPLATE_INSTANTIATION (decl)
+         && ! DECL_IN_AGGR_P (decl))
+       {
+         import_export_decl (decl);
+         DECL_EXTERNAL (decl) = ! DECL_NOT_REALLY_EXTERN (decl);
+       }
+    }
+
   vars = static_aggregates;
 
   if (static_ctors || vars || might_have_exceptions_p ())
@@ -2925,10 +2974,23 @@ finish_file ()
       tree type = TREE_TYPE (decl);
       tree temp = TREE_PURPOSE (vars);
 
-      if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars))
+      if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars)
+         && ! DECL_EXTERNAL (decl))
        {
          temp = build_cleanup (decl);
+
+         if (DECL_COMMON (decl))
+           {
+             tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
+             sentry = build_unary_op (PREDECREMENT_EXPR, sentry, 0);
+             sentry = build_binary_op (EQ_EXPR, sentry, integer_zero_node, 1);
+             expand_start_cond (sentry, 0);
+           }
+
          expand_expr_stmt (temp);
+
+         if (DECL_COMMON (decl))
+           expand_end_cond ();
        }
     }
 
@@ -2983,11 +3045,12 @@ finish_file ()
             then don't initialize it here.  Also, don't bother
             with initializers that contain errors.  */
          if (TREE_STATIC (vars)
+             || DECL_EXTERNAL (decl)
              || (init && TREE_CODE (init) == TREE_LIST
                  && value_member (error_mark_node, init)))
            {
              vars = TREE_CHAIN (vars);
-             continue;
+             goto next_mess;
            }
 
          if (TREE_CODE (decl) == VAR_DECL)
@@ -3003,6 +3066,15 @@ finish_file ()
              DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
              DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
 
+             if (DECL_COMMON (decl))
+               {
+                 tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
+                 sentry = build_unary_op (PREINCREMENT_EXPR, sentry, 0);
+                 sentry = build_binary_op
+                   (EQ_EXPR, sentry, integer_one_node, 1);
+                 expand_start_cond (sentry, 0);
+               }
+
              if (IS_AGGR_TYPE (TREE_TYPE (decl))
                  || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
                expand_aggr_init (decl, init, 0, 0);
@@ -3016,32 +3088,19 @@ finish_file ()
              else
                expand_assignment (decl, init, 0, 0);
 
+             if (DECL_COMMON (decl))
+               expand_end_cond ();
+
              DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
              DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
            }
-         else if (TREE_CODE (decl) == SAVE_EXPR)
-           {
-             if (! PARM_DECL_EXPR (decl))
-               {
-                 /* a `new' expression at top level.  */
-                 expand_expr (decl, const0_rtx, VOIDmode, 0);
-                 if (TREE_CODE (init) == TREE_VEC)
-                   {
-                     expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
-                                                   TREE_VEC_ELT (init, 1),
-                                                   TREE_VEC_ELT (init, 2), 0),
-                                  const0_rtx, VOIDmode, 0);
-                   }
-                 else
-                   expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0);
-               }
-           }
          else if (decl == error_mark_node)
            ;
          else my_friendly_abort (22);
 
          /* Cleanup any temporaries needed for the initial value.  */
          expand_cleanups_to (old_cleanups);
+       next_mess:
          pop_temp_slots ();
          pop_temp_slots ();
          target_temp_slot_level = old_temp_level;
@@ -3074,13 +3133,6 @@ finish_file ()
     {
       tree decl = TREE_VALUE (pending_statics);
 
-      if (DECL_TEMPLATE_INSTANTIATION (decl)
-         && ! DECL_IN_AGGR_P (decl))
-       {
-         import_export_decl (decl);
-         DECL_EXTERNAL (decl) = ! DECL_NOT_REALLY_EXTERN (decl);
-       }
-
       if (TREE_USED (decl) == 1
          || TREE_READONLY (decl) == 0
          || DECL_INITIAL (decl) == 0)
index cdddeaf..8a0735a 100644 (file)
@@ -1085,6 +1085,18 @@ build_overload_with_type (name, type)
   return get_identifier (obstack_base (&scratch_obstack));
 }
 
+tree
+get_id_2 (name, name2)
+     char *name;
+     tree name2;
+{
+  OB_INIT ();
+  OB_PUTCP (name);
+  OB_PUTID (name2);
+  OB_FINISH ();
+  return get_identifier (obstack_base (&scratch_obstack));
+}
+
 /* Top-level interface to explicit overload requests. Allow NAME
    to be overloaded. Error if NAME is already declared for the current
    scope. Warning if function is redundantly overloaded. */
index 6883572..7f8d2a0 100644 (file)
@@ -88,7 +88,8 @@ empty_parms ()
 {
   tree parms;
 
-  if (strict_prototype)
+  if (strict_prototype
+      || current_class_type != NULL)
     parms = void_list_node;
   else
     parms = NULL_TREE;
@@ -265,6 +266,8 @@ empty_parms ()
 %type <ttype> named_class_head_sans_basetype_defn
 %type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
 
+%type <ttype> self_template_type
+
 %token NSNAME
 %type <ttype> NSNAME
 
@@ -595,6 +598,48 @@ constructor_declarator:
                    }
                  $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $5);
                }
+       | nested_name_specifier self_template_type '(' 
+               {
+                 $$ = build_parse_node (SCOPE_REF, $1, $2);
+                 if ($1 != current_class_type)
+                   {
+                     push_nested_class ($1, 3);
+                     TREE_COMPLEXITY ($$) = current_class_depth;
+                   }
+               }
+         parmlist ')' type_quals
+               { $$ = build_parse_node (CALL_EXPR, $<ttype>4, $5, $7); }
+       | nested_name_specifier self_template_type LEFT_RIGHT type_quals
+               {
+                 $$ = build_parse_node (SCOPE_REF, $1, $2);
+                 if ($1 != current_class_type)
+                   {
+                     push_nested_class ($1, 3);
+                     TREE_COMPLEXITY ($$) = current_class_depth;
+                   }
+                 $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $4);
+               }
+       | global_scope nested_name_specifier self_template_type '(' 
+               {
+                 $$ = build_parse_node (SCOPE_REF, $2, $3);
+                 if ($2 != current_class_type)
+                   {
+                     push_nested_class ($2, 3);
+                     TREE_COMPLEXITY ($$) = current_class_depth;
+                   }
+               }
+        parmlist ')' type_quals
+               { $$ = build_parse_node (CALL_EXPR, $<ttype>5, $6, $8); }
+       | global_scope nested_name_specifier self_template_type LEFT_RIGHT type_quals
+               {
+                 $$ = build_parse_node (SCOPE_REF, $2, $3);
+                 if ($2 != current_class_type)
+                   {
+                     push_nested_class ($2, 3);
+                     TREE_COMPLEXITY ($$) = current_class_depth;
+                   }
+                 $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $5);
+               }
        ;
 
 fn.def1:
@@ -636,6 +681,10 @@ component_constructor_declarator:
                { $$ = build_parse_node (CALL_EXPR, $1, $3, $5); }
        | SELFNAME LEFT_RIGHT type_quals
                { $$ = build_parse_node (CALL_EXPR, $1, empty_parms (), $3); }
+       | self_template_type '(' parmlist ')' type_quals
+               { $$ = build_parse_node (CALL_EXPR, $1, $3, $5); }
+       | self_template_type LEFT_RIGHT type_quals
+               { $$ = build_parse_node (CALL_EXPR, $1, empty_parms (), $3); }
        ;
 
 /* more C++ complexity.  See component_decl for a comment on the
@@ -826,7 +875,11 @@ template_type:
                  if ($$ != error_mark_node)
                    $$ = TYPE_STUB_DECL ($$);
                }
-       | SELFNAME  '<' template_arg_list template_close_bracket
+       | self_template_type
+       ;
+
+self_template_type:
+         SELFNAME  '<' template_arg_list template_close_bracket
                {
                  $$ = lookup_template_class ($1, $3, NULL_TREE);
                  if ($$ != error_mark_node)
index eaac1f1..5d1dfce 100644 (file)
@@ -463,10 +463,12 @@ comp_template_args (oldargs, newargs)
        continue;
       if (TREE_CODE (nt) != TREE_CODE (ot))
        return 0;
-      if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't' && comptypes (ot, nt, 1))
-       continue;
-      if (TREE_CODE (ot) == TEMPLATE_CONST_PARM
-         && TEMPLATE_CONST_IDX (nt) == TEMPLATE_CONST_IDX (ot))
+      if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
+       {
+         if (comptypes (ot, nt, 1))
+           continue;
+       }
+      else if (cp_tree_equal (ot, nt) > 0)
        continue;
       return 0;
     }
@@ -2080,7 +2082,7 @@ tsubst_expr (t, args, nargs, in_decl)
     case DECL_STMT:
       {
        int i = suspend_momentary ();
-       tree dcl;
+       tree dcl, init;
 
        lineno = TREE_COMPLEXITY (t);
        emit_line_note (input_filename, lineno);
@@ -2089,9 +2091,9 @@ tsubst_expr (t, args, nargs, in_decl)
           tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl),
           TREE_OPERAND (t, 3) != 0,
           tsubst (TREE_OPERAND (t, 2), args, nargs, in_decl));
+       init = tsubst_expr (TREE_OPERAND (t, 3), args, nargs, in_decl);
        cp_finish_decl
-         (dcl, tsubst_expr (TREE_OPERAND (t, 3), args, nargs, in_decl),
-          NULL_TREE, 1, LOOKUP_ONLYCONVERTING);
+         (dcl, init, NULL_TREE, 1, init ? LOOKUP_ONLYCONVERTING : 0);
        resume_momentary (i);
        return dcl;
       }
index 45de00f..37e6698 100644 (file)
@@ -248,6 +248,7 @@ get_tinfo_fn (type)
   TREE_TYPE (name) = type;
   pushdecl_top_level (d);
   make_function_rtl (d);
+  assemble_external (d);
   mark_inline_for_output (d);
   if (at_eof)
     import_export_decl (d);
@@ -312,6 +313,7 @@ throw_bad_cast ()
   DECL_ARTIFICIAL (d) = 1;
   pushdecl_top_level (d);
   make_function_rtl (d);
+  assemble_external (d);
 
   pop_obstacks ();
 
@@ -519,6 +521,7 @@ build_dynamic_cast (type, expr)
              DECL_ARTIFICIAL (dcast_fn) = 1;
              pushdecl_top_level (dcast_fn);
              make_function_rtl (dcast_fn);
+             assemble_external (dcast_fn);
              pop_obstacks ();
            }
          
@@ -603,6 +606,7 @@ expand_si_desc (tdecl, type)
       DECL_ARTIFICIAL (fn) = 1;
       pushdecl_top_level (fn);
       make_function_rtl (fn);
+      assemble_external (fn);
       pop_obstacks ();
     }
 
@@ -782,6 +786,7 @@ expand_class_desc (tdecl, type)
       DECL_ARTIFICIAL (fn) = 1;
       pushdecl_top_level (fn);
       make_function_rtl (fn);
+      assemble_external (fn);
       pop_obstacks ();
     }
 
@@ -829,6 +834,7 @@ expand_ptr_desc (tdecl, type)
       DECL_ARTIFICIAL (fn) = 1;
       pushdecl_top_level (fn);
       make_function_rtl (fn);
+      assemble_external (fn);
       pop_obstacks ();
     }
 
@@ -879,6 +885,7 @@ expand_attr_desc (tdecl, type)
       DECL_ARTIFICIAL (fn) = 1;
       pushdecl_top_level (fn);
       make_function_rtl (fn);
+      assemble_external (fn);
       pop_obstacks ();
     }
 
@@ -920,6 +927,7 @@ expand_generic_desc (tdecl, type, fnname)
       DECL_ARTIFICIAL (fn) = 1;
       pushdecl_top_level (fn);
       make_function_rtl (fn);
+      assemble_external (fn);
       pop_obstacks ();
     }
 
index 6db1069..11cc90d 100644 (file)
@@ -2013,3 +2013,130 @@ hack_decl_function_context (decl)
     return decl_function_context (TYPE_MAIN_DECL (DECL_CLASS_CONTEXT (decl)));
   return decl_function_context (decl);
 }
+
+/* Return truthvalue of whether T1 is the same tree structure as T2.
+   Return 1 if they are the same.
+   Return 0 if they are understandably different.
+   Return -1 if either contains tree structure not understood by
+   this function.  */
+
+int
+cp_tree_equal (t1, t2)
+     tree t1, t2;
+{
+  register enum tree_code code1, code2;
+  int cmp;
+
+  if (t1 == t2)
+    return 1;
+  if (t1 == 0 || t2 == 0)
+    return 0;
+
+  code1 = TREE_CODE (t1);
+  code2 = TREE_CODE (t2);
+
+  if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
+    if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR)
+      return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+    else
+      return cp_tree_equal (TREE_OPERAND (t1, 0), t2);
+  else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
+          || code2 == NON_LVALUE_EXPR)
+    return cp_tree_equal (t1, TREE_OPERAND (t2, 0));
+
+  if (code1 != code2)
+    return 0;
+
+  switch (code1)
+    {
+    case INTEGER_CST:
+      return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
+       && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
+
+    case REAL_CST:
+      return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
+
+    case STRING_CST:
+      return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
+       && !bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+                 TREE_STRING_LENGTH (t1));
+
+    case CONSTRUCTOR:
+      abort ();
+
+    case SAVE_EXPR:
+      return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+
+    case CALL_EXPR:
+      cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+      if (cmp <= 0)
+       return cmp;
+      return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+
+    case TARGET_EXPR:
+      /* Special case: if either target is an unallocated VAR_DECL,
+        it means that it's going to be unified with whatever the
+        TARGET_EXPR is really supposed to initialize, so treat it
+        as being equivalent to anything.  */
+      if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL
+          && DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE
+          && DECL_RTL (TREE_OPERAND (t1, 0)) == 0)
+         || (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL
+             && DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE
+             && DECL_RTL (TREE_OPERAND (t2, 0)) == 0))
+       cmp = 1;
+      else
+       cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+      if (cmp <= 0)
+       return cmp;
+      return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+
+    case WITH_CLEANUP_EXPR:
+      cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+      if (cmp <= 0)
+       return cmp;
+      return cp_tree_equal (TREE_OPERAND (t1, 2), TREE_OPERAND (t1, 2));
+
+    case COMPONENT_REF:
+      if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1))
+       return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+      return 0;
+
+    case VAR_DECL:
+    case PARM_DECL:
+    case CONST_DECL:
+    case FUNCTION_DECL:
+      return 0;
+
+    case TEMPLATE_CONST_PARM:
+      return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2);
+
+    case SIZEOF_EXPR:
+      if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
+       return 0;
+      if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t1, 0))) == 't')
+       return comptypes (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), 1);
+      break;
+    }
+
+  switch (TREE_CODE_CLASS (code1))
+    {
+      int i;
+    case '1':
+    case '2':
+    case '<':
+    case 'e':
+    case 'r':
+    case 's':
+      cmp = 1;
+      for (i=0; i<tree_code_length[(int) code1]; ++i)
+       {
+         cmp = cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
+         if (cmp <= 0)
+           return cmp;
+       }
+      return cmp;
+    }
+
+  return -1;
+}
index 85accd8..0b7554c 100644 (file)
@@ -437,6 +437,10 @@ common_type (t1, t2)
 
     case ARRAY_TYPE:
       {
+       int constp 
+         = TYPE_READONLY (t1) || TYPE_READONLY (t2);
+       int volatilep
+         = TYPE_VOLATILE (t1) || TYPE_VOLATILE (t2);
        tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
        /* Save space: see if the result is identical to one of the args.  */
        if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
@@ -444,7 +448,9 @@ common_type (t1, t2)
        if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
          return build_type_attribute_variant (t2, attributes);
        /* Merge the element types, and have a size if either arg has one.  */
-       t1 = build_cplus_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+       t1 = build_cplus_array_type (TYPE_MAIN_VARIANT (elt), TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+       if (constp || volatilep)
+         t1 = cp_build_type_variant (t1, constp, volatilep);
        return build_type_attribute_variant (t1, attributes);
       }