2003-01-16 Jeffrey D. Oldham <oldham@codesourcery.com>
authoroldham <oldham@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 16 Jan 2003 22:06:04 +0000 (22:06 +0000)
committeroldham <oldham@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 16 Jan 2003 22:06:04 +0000 (22:06 +0000)
* cp-tree.h (tsubst_copy_and_build): New declaration.
* pt.c (tsubst_copy): Remove 'build_expr_from_tree' from comment.
(tsubst_expr): Use 'tsubst_copy_and_build'.  Update initial comment.
(tsubst_copy_and_build): New function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@61409 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c

index aea2a4c..54d66be 100644 (file)
@@ -1,3 +1,10 @@
+2003-01-16  Jeffrey D. Oldham  <oldham@codesourcery.com>
+
+       * cp-tree.h (tsubst_copy_and_build): New declaration.
+       * pt.c (tsubst_copy): Remove 'build_expr_from_tree' from comment.
+       (tsubst_expr): Use 'tsubst_copy_and_build'.  Update initial comment.
+       (tsubst_copy_and_build): New function.
+
 2003-01-16  Mark Mitchell  <mark@codesourcery.com>
 
        * cp-tree.h (lang_type_class): Remove is_partial_instantiation.
index 90c2e59..9d06763 100644 (file)
@@ -4025,6 +4025,7 @@ extern tree get_innermost_template_args         (tree, int);
 extern tree tsubst                             (tree, tree, tsubst_flags_t, tree);
 extern tree tsubst_expr                                (tree, tree, tsubst_flags_t, tree);
 extern tree tsubst_copy                                (tree, tree, tsubst_flags_t, tree);
+extern tree tsubst_copy_and_build              (tree, tree, tsubst_flags_t, tree);
 extern void maybe_begin_member_template_processing (tree);
 extern void maybe_end_member_template_processing (void);
 extern tree finish_member_template_decl         (tree);
index 91cf89c..c037676 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle parameterized types (templates) for GNU C++.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002  Free Software Foundation, Inc.
+   2001, 2002, 2003  Free Software Foundation, Inc.
    Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
    Rewritten by Jason Merrill (jason@cygnus.com).
 
@@ -7360,11 +7360,10 @@ tsubst_copy (t, args, complain, in_decl)
         NULL_TREE);
 
     case STMT_EXPR:
-      /* This processing should really occur in tsubst_expr, However,
+      /* This processing should really occur in tsubst_expr However,
         tsubst_expr does not recurse into expressions, since it
-        assumes that there aren't any statements inside them.
-        Instead, it simply calls build_expr_from_tree.  So, we need
-        to expand the STMT_EXPR here.  */
+        assumes that there aren't any statements inside them.  So, we
+        need to expand the STMT_EXPR here.  */
       if (!processing_template_decl)
        {
          tree stmt_expr = begin_stmt_expr ();
@@ -7501,7 +7500,8 @@ tsubst_copy (t, args, complain, in_decl)
     }
 }
 
-/* Like tsubst_copy, but also does semantic processing.  */
+/* Like tsubst_copy for expressions, etc. but also does semantic
+   processing.  */
 
 tree
 tsubst_expr (t, args, complain, in_decl)
@@ -7518,7 +7518,7 @@ tsubst_expr (t, args, complain, in_decl)
     return tsubst_copy (t, args, complain, in_decl);
 
   if (!statement_code_p (TREE_CODE (t)))
-    return build_expr_from_tree (tsubst_copy (t, args, complain, in_decl));
+    return tsubst_copy_and_build (t, args, complain, in_decl);
     
   switch (TREE_CODE (t))
     {
@@ -7827,6 +7827,508 @@ tsubst_expr (t, args, complain, in_decl)
   return tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
 }
 
+/* Like tsubst but deals with expressions and performs semantic
+   analysis.  */
+
+tree
+tsubst_copy_and_build (t, args, complain, in_decl)
+     tree t, args;
+     tsubst_flags_t complain;
+     tree in_decl;
+{
+  if (t == NULL_TREE || t == error_mark_node)
+    return t;
+
+  switch (TREE_CODE (t))
+    {
+    case IDENTIFIER_NODE:
+      if (IDENTIFIER_TYPENAME_P (t))
+       {
+         tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+         return do_identifier (mangle_conv_op_name_for_type (new_type),
+                               NULL_TREE);
+       }
+      else
+       return do_identifier (t, NULL_TREE);
+
+    case LOOKUP_EXPR:
+      {
+       if (LOOKUP_EXPR_GLOBAL (t))
+         {
+           tree token
+             = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+           return do_scoped_id (token, IDENTIFIER_GLOBAL_VALUE (token));
+         }
+       else
+         {
+           t = do_identifier
+             (tsubst_copy
+              (TREE_OPERAND (t, 0), args, complain, in_decl),
+              NULL_TREE);
+           if (TREE_CODE (t) == ALIAS_DECL)
+             t = DECL_INITIAL (t);
+           return t;
+         }
+      }
+
+    case TEMPLATE_ID_EXPR:
+      {
+       tree object;
+       tree template
+         = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+       
+       if (TREE_CODE (template) == COMPONENT_REF)
+         {
+           object = TREE_OPERAND (template, 0);
+           template = TREE_OPERAND (template, 1);
+         }
+       else
+         object = NULL_TREE;
+
+       template = lookup_template_function
+         (template,
+          tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+       
+       if (object)
+         return build (COMPONENT_REF, TREE_TYPE (template), 
+                       object, template);
+       else
+         return template;
+      }
+
+    case INDIRECT_REF:
+      return build_x_indirect_ref
+       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
+        "unary *");
+
+    case CAST_EXPR:
+      return build_functional_cast
+       (tsubst (TREE_TYPE (t), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+
+    case REINTERPRET_CAST_EXPR:
+      return build_reinterpret_cast
+       (tsubst (TREE_TYPE (t), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+
+    case CONST_CAST_EXPR:
+      return build_const_cast
+       (tsubst (TREE_TYPE (t), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+
+    case DYNAMIC_CAST_EXPR:
+      return build_dynamic_cast
+       (tsubst (TREE_TYPE (t), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+
+    case STATIC_CAST_EXPR:
+      return build_static_cast
+       (tsubst (TREE_TYPE (t), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+      if (TREE_TYPE (t))
+       return tsubst_copy (t, args, complain, in_decl);
+      else
+       return build_x_unary_op
+         (TREE_CODE (t),
+          tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
+                                 in_decl));
+
+    case NEGATE_EXPR:
+    case BIT_NOT_EXPR:
+      if (TREE_TYPE (t))
+       return tsubst_copy (t, args, complain, in_decl);
+      else
+       return build_x_unary_op
+         (TREE_CODE (t),
+          tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
+                                 in_decl));
+
+    case ABS_EXPR:
+      if (TREE_TYPE (t))
+       return t;
+      return build_x_unary_op
+       (TREE_CODE (t),
+        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+
+    case TRUTH_NOT_EXPR:
+    case ADDR_EXPR:
+    case CONVERT_EXPR:  /* Unary + */
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      if (TREE_TYPE (t))
+       return tsubst_copy (t, args, complain, in_decl);
+      else
+       return build_x_unary_op
+         (TREE_CODE (t),
+          tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
+                                 in_decl));
+
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case BIT_AND_EXPR:
+    case BIT_ANDTC_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case TRUNC_MOD_EXPR:
+    case FLOOR_MOD_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case RSHIFT_EXPR:
+    case LSHIFT_EXPR:
+    case RROTATE_EXPR:
+    case LROTATE_EXPR:
+    case EQ_EXPR:
+    case NE_EXPR:
+    case MAX_EXPR:
+    case MIN_EXPR:
+    case LE_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case GT_EXPR:
+    case MEMBER_REF:
+      return build_x_binary_op
+       (TREE_CODE (t), 
+        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
+
+    case DOTSTAR_EXPR:
+      return build_m_component_ref
+       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
+
+    case SCOPE_REF:
+      return build_offset_ref
+       (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+        tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+
+    case ARRAY_REF:
+      {
+       if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
+           == NULL_TREE)
+         /* new-type-id */
+         return build_nt
+           (ARRAY_REF, NULL_TREE,
+            tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
+                                   in_decl));
+       
+       return grok_array_decl
+         (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
+                                 in_decl),
+          tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
+                                 in_decl));
+      }
+
+    case SIZEOF_EXPR:
+    case ALIGNOF_EXPR:
+      {
+       tree r =
+         tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl);
+       if (!TYPE_P (r))
+         return TREE_CODE (t) == SIZEOF_EXPR ?
+           expr_sizeof (r) : c_alignof_expr (r);
+       else
+         return cxx_sizeof_or_alignof_type (r, TREE_CODE (t), true);
+      }
+
+    case MODOP_EXPR:
+      return build_x_modify_expr
+       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
+        TREE_CODE (TREE_OPERAND (t, 1)),
+        tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
+
+    case ARROW_EXPR:
+      return build_x_arrow
+       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+
+    case NEW_EXPR:
+      return build_new
+       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl),
+        NEW_EXPR_USE_GLOBAL (t));
+
+    case DELETE_EXPR:
+     return delete_sanity
+       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
+       tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
+       DELETE_EXPR_USE_VEC (t),
+       DELETE_EXPR_USE_GLOBAL (t));
+
+    case COMPOUND_EXPR:
+      {
+       if (tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl)
+           == NULL_TREE)
+         return build_x_compound_expr
+           (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
+                                   in_decl));
+       else
+         abort ();
+      }
+
+    case METHOD_CALL_EXPR:
+      {
+       tree method
+         = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+       
+       if (TREE_CODE (method) == SCOPE_REF)
+         {
+           tree name = TREE_OPERAND (method, 1);
+         
+           if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+             name = build_nt (TEMPLATE_ID_EXPR,
+                              TREE_OPERAND (name, 0),
+                              TREE_OPERAND (name, 1));
+           
+           return build_scoped_method_call
+             (tsubst_copy_and_build
+              (TREE_OPERAND (t, 1), args, complain, in_decl),
+              TREE_OPERAND (method, 0),
+              name,
+              tsubst_copy_and_build
+              (TREE_OPERAND (t, 2), args, complain, in_decl));
+         }
+       else 
+         {
+           /* We can get a TEMPLATE_ID_EXPR here on code like:
+
+           x->f<2>();
+             
+           so we must resolve that.  However, we can also get things
+           like a BIT_NOT_EXPR here, when referring to a destructor,
+           and things like that are not correctly resolved by this
+           function so just use it when we really need it.  */
+           if (TREE_CODE (method) == TEMPLATE_ID_EXPR)
+             method = lookup_template_function
+               (TREE_OPERAND (method, 0),
+                TREE_OPERAND (method, 1));
+
+           return build_method_call
+             (tsubst_copy_and_build
+              (TREE_OPERAND (t, 1), args, complain, in_decl),
+              method,
+              tsubst_copy_and_build
+              (TREE_OPERAND (t, 2), args, complain, in_decl),
+              NULL_TREE, LOOKUP_NORMAL);
+         }
+      }
+
+    case CALL_EXPR:
+      {
+       tree function
+         = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+       if (TREE_CODE (function) == SCOPE_REF)
+         {
+           tree name = TREE_OPERAND (function, 1);
+           if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+             name = build_nt (TEMPLATE_ID_EXPR,
+                              TREE_OPERAND (name, 0),
+                              TREE_OPERAND (name, 1));
+
+           return build_call_from_tree
+             (resolve_scoped_fn_name (TREE_OPERAND (function, 0), name),
+              tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
+                                     in_decl),
+              1);
+         }
+       else
+         {
+           tree name = function;
+           tree id;
+           tree copy_args = tsubst_copy_and_build
+             (TREE_OPERAND (t, 1), args, complain, in_decl);
+           if (copy_args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
+               && !LOOKUP_EXPR_GLOBAL (name)
+               && (TREE_CODE ((id = TREE_OPERAND (name, 0)))
+                   == IDENTIFIER_NODE)
+               && (!current_class_type
+                   || !lookup_member (current_class_type, id, 0, 0)))
+             {
+               /* Do Koenig lookup if there are no class members.  */
+               name = do_identifier (id, copy_args);
+             }
+           else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
+                    || ! really_overloaded_fn (name))
+             name = build_expr_from_tree (name);
+
+           if (TREE_CODE (name) == OFFSET_REF)
+             return build_offset_ref_call_from_tree (name, copy_args);
+           if (TREE_CODE (name) == COMPONENT_REF)
+             return finish_object_call_expr (TREE_OPERAND (name, 1),
+                                             TREE_OPERAND (name, 0),
+                                             copy_args);
+           name = convert_from_reference (name);
+           return build_call_from_tree (name, copy_args, 
+                                        /*disallow_virtual=*/false);
+         }
+      }
+
+    case COND_EXPR:
+      return build_x_conditional_expr
+       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
+
+    case PSEUDO_DTOR_EXPR:
+      return finish_pseudo_destructor_expr 
+       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
+        tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
+
+    case TREE_LIST:
+      {
+       tree purpose, value, chain;
+
+       if (t == void_list_node)
+         return t;
+
+       purpose = TREE_PURPOSE (t);
+       if (purpose)
+         purpose = tsubst_copy_and_build (purpose, args, complain, in_decl);
+       value = TREE_VALUE (t);
+       if (value)
+         value = tsubst_copy_and_build (value, args, complain, in_decl);
+       chain = TREE_CHAIN (t);
+       if (chain && chain != void_type_node)
+         chain = tsubst_copy_and_build (chain, args, complain, in_decl);
+       if (purpose == TREE_PURPOSE (t)
+           && value == TREE_VALUE (t)
+           && chain == TREE_CHAIN (t))
+         return t;
+       return tree_cons (purpose, value, chain);
+      }
+
+    case COMPONENT_REF:
+      {
+       tree object =
+         tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl);
+       tree member =
+         tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+
+       if (!CLASS_TYPE_P (TREE_TYPE (object)))
+         {
+           if (TREE_CODE (member) == BIT_NOT_EXPR)
+             return finish_pseudo_destructor_expr (object, 
+                                                   NULL_TREE,
+                                                   TREE_TYPE (object));
+           else if (TREE_CODE (member) == SCOPE_REF
+                    && (TREE_CODE (TREE_OPERAND (member, 1)) == BIT_NOT_EXPR))
+             return finish_pseudo_destructor_expr (object, 
+                                                   object,
+                                                   TREE_TYPE (object));
+         }
+       else if (TREE_CODE (member) == SCOPE_REF
+                && TREE_CODE (TREE_OPERAND (member, 1)) == TEMPLATE_ID_EXPR)
+         {
+           tree tmpl;
+           tree args;
+       
+           /* Lookup the template functions now that we know what the
+              scope is.  */
+           tmpl = TREE_OPERAND (TREE_OPERAND (member, 1), 0);
+           args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
+           member = lookup_qualified_name (TREE_OPERAND (member, 0),
+                                           tmpl, 
+                                           /*is_type=*/0,
+                                           /*flags=*/0);
+           if (BASELINK_P (member))
+             BASELINK_FUNCTIONS (member) 
+               = build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
+                           args);
+           else
+             {
+               error ("`%D' is not a member of `%T'",
+                      tmpl, TREE_TYPE (object));
+               return error_mark_node;
+             }
+         }
+
+       return finish_class_member_access_expr (object, member);
+      }
+
+    case THROW_EXPR:
+      return build_throw
+       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+
+    case CONSTRUCTOR:
+      {
+       tree r;
+       tree elts;
+       tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+       bool purpose_p;
+
+       /* digest_init will do the wrong thing if we let it.  */
+       if (type && TYPE_PTRMEMFUNC_P (type))
+         return t;
+
+       r = NULL_TREE;
+       /* We do not want to process the purpose of aggregate
+          initializers as they are identifier nodes which will be
+          looked up by digest_init.  */
+       purpose_p = !(type && IS_AGGR_TYPE (type));
+       for (elts = tsubst_copy (CONSTRUCTOR_ELTS (t), args, complain,
+                                in_decl);
+            elts;
+            elts = TREE_CHAIN (elts))
+         {
+           tree purpose = TREE_PURPOSE (elts);
+           tree value = TREE_VALUE (elts);
+           
+           if (purpose && purpose_p)
+             purpose
+               = tsubst_copy_and_build (purpose, args, complain, in_decl);
+           value = tsubst_copy_and_build (value, args, complain, in_decl);
+           r = tree_cons (purpose, value, r);
+         }
+       
+       r = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (r));
+       TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
+
+       if (type)
+         return digest_init (type, r, 0);
+       return r;
+      }
+
+    case TYPEID_EXPR:
+      {
+       tree operand_0
+         = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
+                                  in_decl);
+       
+       if (TYPE_P (operand_0))
+         return get_typeid (operand_0);
+       return build_typeid (operand_0);
+      }
+
+    case PARM_DECL:
+      return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
+
+    case VAR_DECL:
+      return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
+
+    case VA_ARG_EXPR:
+       return build_x_va_arg
+         (tsubst_copy_and_build
+          (TREE_OPERAND (t, 0), args, complain, in_decl),
+          tsubst_copy (TREE_TYPE (t), args, complain, in_decl));
+
+    default:
+      return tsubst_copy (t, args, complain, in_decl);
+    }
+}
+
 /* Instantiate the indicated variable or function template TMPL with
    the template arguments in TARG_PTR.  */