OSDN Git Service

PR c++/28903
[pf3gnuchains/gcc-fork.git] / gcc / cp / pt.c
index a81f6a0..715b946 100644 (file)
@@ -159,7 +159,7 @@ static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
 static int eq_local_specializations (const void *, const void *);
 static bool dependent_type_p_r (tree);
 static tree tsubst (tree, tree, tsubst_flags_t, tree);
-static tree tsubst_expr        (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_expr        (tree, tree, tsubst_flags_t, tree, bool);
 static tree tsubst_copy        (tree, tree, tsubst_flags_t, tree);
 
 /* Make the current scope suitable for access checking when we are
@@ -337,6 +337,10 @@ push_inline_template_parms_recursive (tree parmlist, int levels)
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
     {
       tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+
+      if (parm == error_mark_node)
+       continue;
+
       gcc_assert (DECL_P (parm));
 
       switch (TREE_CODE (parm))
@@ -669,13 +673,20 @@ check_explicit_instantiation_namespace (tree spec)
 /* The TYPE is being declared.  If it is a template type, that means it
    is a partial specialization.  Do appropriate error-checking.  */
 
-void
+tree
 maybe_process_partial_specialization (tree type)
 {
   tree context;
 
   if (type == error_mark_node)
-    return;
+    return error_mark_node;
+
+  if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+    {
+      error ("name of class shadows template template parameter %qD",
+            TYPE_NAME (type));
+      return error_mark_node;
+    }
 
   context = TYPE_CONTEXT (type);
 
@@ -760,7 +771,12 @@ maybe_process_partial_specialization (tree type)
        }
     }
   else if (processing_specialization)
-    error ("explicit specialization of non-template %qT", type);
+    {
+      error ("explicit specialization of non-template %qT", type);
+      return error_mark_node;
+    }
+
+  return type;
 }
 
 /* Returns nonzero if we can optimize the retrieval of specializations
@@ -811,6 +827,9 @@ static tree
 retrieve_specialization (tree tmpl, tree args,
                         bool class_specializations_p)
 {
+  if (args == error_mark_node)
+    return NULL_TREE;
+
   gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
 
   /* There should be as many levels of arguments as there are
@@ -1156,7 +1175,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
            {
              error ("specialization of %qD after instantiation",
                     fn);
-             return spec;
+             return error_mark_node;
            }
          else
            {
@@ -1224,7 +1243,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
      template it is specializing.  */
   if (DECL_TEMPLATE_SPECIALIZATION (spec)
       && !check_specialization_namespace (tmpl))
-    DECL_CONTEXT (spec) = decl_namespace_context (tmpl);
+    DECL_CONTEXT (spec) = FROB_CONTEXT (decl_namespace_context (tmpl));
 
   if (!optimize_specialization_lookup_p (tmpl))
     DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
@@ -2140,13 +2159,7 @@ check_explicit_specialization (tree declarator,
             template it specializes.  */
          TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
          TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
-         /* The specialization has the same visibility as the
-            template it specializes.  */
-         if (DECL_VISIBILITY_SPECIFIED (gen_tmpl))
-           {
-             DECL_VISIBILITY_SPECIFIED (decl) = 1;
-             DECL_VISIBILITY (decl) = DECL_VISIBILITY (gen_tmpl);
-           }
+
          /* If DECL is a friend declaration, declared using an
             unqualified name, the namespace associated with DECL may
             have been set incorrectly.  For example, in:
@@ -2210,8 +2223,13 @@ comp_template_parms (tree parms1, tree parms2)
 
       for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
        {
-         tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
-         tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
+          tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
+          tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
+
+          /* If either of the template parameters are invalid, assume
+             they match for the sake of error recovery. */
+          if (parm1 == error_mark_node || parm2 == error_mark_node)
+            return 1;
 
          if (TREE_CODE (parm1) != TREE_CODE (parm2))
            return 0;
@@ -2343,19 +2361,25 @@ process_template_parm (tree list, tree parm, bool is_non_type)
 {
   tree decl = 0;
   tree defval;
-  int idx;
+  tree err_parm_list;
+  int idx = 0;
 
   gcc_assert (TREE_CODE (parm) == TREE_LIST);
   defval = TREE_PURPOSE (parm);
 
   if (list)
     {
-      tree p = TREE_VALUE (tree_last (list));
+      tree p = tree_last (list);
+
+      if (p && TREE_VALUE (p) != error_mark_node)
+        {
+          p = TREE_VALUE (p);
+          if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
+            idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
+          else
+            idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));
+        }
 
-      if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
-       idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
-      else
-       idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));
       ++idx;
     }
   else
@@ -2368,7 +2392,11 @@ process_template_parm (tree list, tree parm, bool is_non_type)
       SET_DECL_TEMPLATE_PARM_P (parm);
 
       if (TREE_TYPE (parm) == error_mark_node)
-       TREE_TYPE (parm) = void_type_node;
+        {
+          err_parm_list = build_tree_list (defval, parm);
+          TREE_VALUE (err_parm_list) = error_mark_node;
+          return chainon (list, err_parm_list);
+        }
       else
       {
        /* [temp.param]
@@ -2377,7 +2405,11 @@ process_template_parm (tree list, tree parm, bool is_non_type)
           ignored when determining its type.  */
        TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
        if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
-         TREE_TYPE (parm) = void_type_node;
+          {
+            err_parm_list = build_tree_list (defval, parm);
+            TREE_VALUE (err_parm_list) = error_mark_node;
+            return chainon (list, err_parm_list);
+          }
       }
 
       /* A template parameter is not modifiable.  */
@@ -2508,11 +2540,15 @@ current_template_args (void)
            {
              t = TREE_VALUE (t);
 
-             if (TREE_CODE (t) == TYPE_DECL
-                 || TREE_CODE (t) == TEMPLATE_DECL)
-               t = TREE_TYPE (t);
-             else
-               t = DECL_INITIAL (t);
+             if (t != error_mark_node)
+               {
+                 if (TREE_CODE (t) == TYPE_DECL
+                     || TREE_CODE (t) == TEMPLATE_DECL)
+                   t = TREE_TYPE (t);
+                 else
+                   t = DECL_INITIAL (t);
+               }
+
              TREE_VEC_ELT (a, i) = t;
            }
        }
@@ -2844,6 +2880,10 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary, int is_partial)
       for (i = 0; i < ntparms; ++i)
        {
          tree parm = TREE_VEC_ELT (inner_parms, i);
+
+          if (parm == error_mark_node)
+            continue;
+
          if (TREE_PURPOSE (parm))
            seen_def_arg_p = 1;
          else if (seen_def_arg_p)
@@ -2908,18 +2948,23 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary, int is_partial)
 
       ntparms = TREE_VEC_LENGTH (inner_parms);
       for (i = 0; i < ntparms; ++i)
-       if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
-         {
-           if (msg)
-             {
-               error (msg, decl);
-               msg = 0;
-             }
+        {
+          if (TREE_VEC_ELT (inner_parms, i) == error_mark_node)
+            continue;
 
-           /* Clear out the default argument so that we are not
-              confused later.  */
-           TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
-         }
+         if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
+           {
+             if (msg)
+               {
+                 error (msg, decl);
+                 msg = 0;
+               }
+
+             /* Clear out the default argument so that we are not
+                confused later.  */
+             TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
+           }
+        }
 
       /* At this point, if we're still interested in issuing messages,
         they must apply to classes surrounding the object declared.  */
@@ -2999,7 +3044,13 @@ push_template_decl_real (tree decl, bool is_friend)
     DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
 
   /* See if this is a primary template.  */
-  primary = template_parm_scope_p ();
+  if (is_friend && ctx)
+    /* A friend template that specifies a class context, i.e.
+         template <typename T> friend void A<T>::f();
+       is not primary.  */
+    primary = 0;
+  else
+    primary = template_parm_scope_p ();
 
   if (primary)
     {
@@ -3305,16 +3356,26 @@ redeclare_class_template (tree type, tree parms)
 
   for (i = 0; i < TREE_VEC_LENGTH (tmpl_parms); ++i)
     {
-      tree tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i));
-      tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
-      tree tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i));
-      tree parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+      tree tmpl_parm;
+      tree parm;
+      tree tmpl_default;
+      tree parm_default;
+
+      if (TREE_VEC_ELT (tmpl_parms, i) == error_mark_node
+          || TREE_VEC_ELT (parms, i) == error_mark_node)
+        continue;
+
+      tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i));
+      parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+      tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i));
+      parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
 
       /* TMPL_PARM and PARM can be either TYPE_DECL, PARM_DECL, or
         TEMPLATE_DECL.  */
-      if (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
-         || (TREE_CODE (tmpl_parm) != TYPE_DECL
-             && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm))))
+      if (tmpl_parm != error_mark_node
+          && (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
+          || (TREE_CODE (tmpl_parm) != TYPE_DECL
+              && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))))
        {
          error ("template parameter %q+#D", tmpl_parm);
          error ("redeclared here as %q#D", parm);
@@ -3368,7 +3429,8 @@ fold_non_dependent_expr (tree expr)
                                    /*args=*/NULL_TREE,
                                    tf_error,
                                    /*in_decl=*/NULL_TREE,
-                                   /*function_p=*/false);
+                                   /*function_p=*/false,
+                                   /*integral_constant_expression_p=*/true);
       processing_template_decl = saved_processing_template_decl;
     }
   return expr;
@@ -3415,7 +3477,9 @@ convert_nontype_argument_function (tree type, tree expr)
   fn_no_ptr = fn;
   if (TREE_CODE (fn_no_ptr) == ADDR_EXPR)
     fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
-
+  if (TREE_CODE (fn_no_ptr) == BASELINK)
+    fn_no_ptr = BASELINK_FUNCTIONS (fn_no_ptr);
   /* [temp.arg.nontype]/1
 
      A template-argument for a non-type, non-template template-parameter
@@ -3592,9 +3656,9 @@ convert_nontype_argument (tree type, tree expr)
 
       if (!constant_address_p)
        {
-           error ("%qE is not a valid template argument for type %qT "
-                 "because it is not a constant pointer", expr, type);
-           return NULL_TREE;
+         error ("%qE is not a valid template argument for type %qT "
+                "because it is not a constant pointer", expr, type);
+         return NULL_TREE;
        }
     }
   /* [temp.arg.nontype]/5, bullet 3
@@ -3770,6 +3834,10 @@ coerce_template_template_parms (tree parm_parms,
 
   for (i = 0; i < nparms; ++i)
     {
+      if (TREE_VEC_ELT (parm_parms, i) == error_mark_node
+          || TREE_VEC_ELT (arg_parms, i) == error_mark_node)
+        continue;
+
       parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
       arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
 
@@ -4029,7 +4097,8 @@ coerce_template_parms (tree parms,
       || (nargs < nparms
          && require_all_args
          && (!use_default_args
-             || !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)))))
+             || (TREE_VEC_ELT (parms, nargs) != error_mark_node
+                  && !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs))))))
     {
       if (complain & tf_error)
        {
@@ -4052,6 +4121,12 @@ coerce_template_parms (tree parms,
 
       /* Get the Ith template parameter.  */
       parm = TREE_VEC_ELT (parms, i);
+      if (parm == error_mark_node)
+      {
+        TREE_VEC_ELT (new_inner_args, i) = error_mark_node;
+        continue;
+      }
 
       /* Calculate the Ith argument.  */
       if (i < nargs)
@@ -4152,8 +4227,14 @@ mangle_class_name_for_template (const char* name, tree parms, tree arglist)
   gcc_assert (nparms == TREE_VEC_LENGTH (arglist));
   for (i = 0; i < nparms; i++)
     {
-      tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
-      tree arg = TREE_VEC_ELT (arglist, i);
+      tree parm;
+      tree arg;
+
+      parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+      arg = TREE_VEC_ELT (arglist, i);
+
+      if (parm == error_mark_node)
+       continue;
 
       if (i)
        ccat (',');
@@ -4782,6 +4863,10 @@ lookup_template_class (tree d1,
           code that generates debugging information will crash.  */
        DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
 
+      /* Possibly limit visibility based on template args.  */
+      TREE_PUBLIC (type_decl) = 1;
+      determine_visibility (type_decl);
+
       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
     }
   timevar_pop (TV_NAME_LOOKUP);
@@ -5172,7 +5257,8 @@ tsubst_friend_function (tree decl, tree args)
         current cless with same name.  */
       push_nested_namespace (ns);
       fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
-                        tf_warning_or_error, NULL_TREE);
+                        tf_warning_or_error, NULL_TREE,
+                        /*integral_constant_expression_p=*/false);
       pop_nested_namespace (ns);
       arglist = tsubst (DECL_TI_ARGS (decl), args,
                        tf_warning_or_error, NULL_TREE);
@@ -5247,6 +5333,10 @@ tsubst_friend_function (tree decl, tree args)
       else
        new_friend_result_template_info = NULL_TREE;
 
+      /* Make the init_value nonzero so pushdecl knows this is a defn.  */
+      if (new_friend_is_defn)
+       DECL_INITIAL (new_friend) = error_mark_node;
+
       /* Inside pushdecl_namespace_level, we will push into the
         current namespace. However, the friend function should go
         into the namespace of the template.  */
@@ -5410,8 +5500,21 @@ tsubst_friend_class (tree friend_tmpl, tree args)
        push_nested_class (tsubst (context, args, tf_none, NULL_TREE));
     }
 
-  /* First, we look for a class template.  */
-  tmpl = lookup_name (DECL_NAME (friend_tmpl));
+  /* Look for a class template declaration.  We look for hidden names
+     because two friend declarations of the same template are the
+     same.  For example, in:
+
+       struct A { 
+         template <typename> friend class F;
+       };
+       template <typename> struct B { 
+         template <typename> friend class F;
+       };
+
+     both F templates are the same.  */
+  tmpl = lookup_name_real (DECL_NAME (friend_tmpl), 0, 0,
+                          /*block_p=*/true, 0, 
+                          LOOKUP_COMPLAIN | LOOKUP_HIDDEN);
 
   /* But, if we don't find one, it might be because we're in a
      situation like this:
@@ -5969,7 +6072,8 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     r = tsubst (t, args, complain, in_decl);
   else
     {
-      r = tsubst_expr (t, args, complain, in_decl);
+      r = tsubst_expr (t, args, complain, in_decl,
+                      /*integral_constant_expression_p=*/true);
       r = fold_non_dependent_expr (r);
     }
   return r;
@@ -6042,9 +6146,20 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
 
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
        {
-         tree tuple = TREE_VEC_ELT (TREE_VALUE (parms), i);
-         tree default_value = TREE_PURPOSE (tuple);
-         tree parm_decl = TREE_VALUE (tuple);
+          tree tuple;
+          tree default_value;
+          tree parm_decl;
+
+          if (parms == error_mark_node)
+            continue;
+
+          tuple = TREE_VEC_ELT (TREE_VALUE (parms), i);
+
+          if (tuple == error_mark_node)
+            continue;
+
+          default_value = TREE_PURPOSE (tuple);
+          parm_decl = TREE_VALUE (tuple);
 
          parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
          if (TREE_CODE (parm_decl) == PARM_DECL
@@ -6183,7 +6298,8 @@ tsubst_default_argument (tree fn, tree type, tree arg)
      stack.  */
   ++function_depth;
   arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
-                    tf_warning_or_error, NULL_TREE);
+                    tf_warning_or_error, NULL_TREE,
+                    /*integral_constant_expression_p=*/false);
   --function_depth;
   pop_deferring_access_checks();
 
@@ -6581,13 +6697,24 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            if (PRIMARY_TEMPLATE_P (gen_tmpl))
              clone_function_decl (r, /*update_method_vec_p=*/0);
          }
-       else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
-         grok_op_properties (r, (complain & tf_error) != 0);
+       else if (IDENTIFIER_OPNAME_P (DECL_NAME (r))
+                && !grok_op_properties (r, (complain & tf_error) != 0))
+         return error_mark_node;
 
        if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
          SET_DECL_FRIEND_CONTEXT (r,
                                   tsubst (DECL_FRIEND_CONTEXT (t),
                                            args, complain, in_decl));
+
+       /* Possibly limit visibility based on template args.  */
+       DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
+       if (DECL_VISIBILITY_SPECIFIED (t))
+         {
+           DECL_VISIBILITY_SPECIFIED (r) = 0;
+           DECL_ATTRIBUTES (r)
+             = remove_attribute ("visibility", DECL_ATTRIBUTES (r));
+         }
+       determine_visibility (r);
       }
       break;
 
@@ -6634,10 +6761,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        TREE_TYPE (r) = type;
        cp_apply_type_quals_to_decl (cp_type_quals (type), r);
 
+       /* DECL_INITIAL gives the number of bits in a bit-field.  */
+       DECL_INITIAL (r)
+         = tsubst_expr (DECL_INITIAL (t), args,
+                        complain, in_decl,
+                        /*integral_constant_expression_p=*/true);
        /* We don't have to set DECL_CONTEXT here; it is set by
           finish_member_declaration.  */
-       DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
-                                       complain, in_decl);
        TREE_CHAIN (r) = NULL_TREE;
        if (VOID_TYPE_P (type))
          error ("instantiation of %q+D as type %qT", r, type);
@@ -6670,7 +6800,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        tree tmpl = NULL_TREE;
        tree ctx;
        tree type = NULL_TREE;
-       int local_p;
+       bool local_p;
 
        if (TREE_CODE (t) == TYPE_DECL)
          {
@@ -6688,40 +6818,64 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
              }
          }
 
-       /* Assume this is a non-local variable.  */
-       local_p = 0;
+       /* Check to see if we already have the specialization we
+          need.  */
+       spec = NULL_TREE;
+       if (DECL_CLASS_SCOPE_P (t) || DECL_NAMESPACE_SCOPE_P (t))
+         {
+           /* T is a static data member or namespace-scope entity.
+              We have to substitute into namespace-scope variables
+              (even though such entities are never templates) because
+              of cases like:
+              
+                template <class T> void f() { extern T t; }
+
+              where the entity referenced is not known until
+              instantiation time.  */
+           local_p = false;
+           ctx = DECL_CONTEXT (t);
+           if (DECL_CLASS_SCOPE_P (t))
+             {
+               ctx = tsubst_aggr_type (ctx, args,
+                                       complain,
+                                       in_decl, /*entering_scope=*/1);
+               /* If CTX is unchanged, then T is in fact the
+                  specialization we want.  That situation occurs when
+                  referencing a static data member within in its own
+                  class.  We can use pointer equality, rather than
+                  same_type_p, because DECL_CONTEXT is always
+                  canonical.  */
+               if (ctx == DECL_CONTEXT (t))
+                 spec = t;
+             }
 
-       if (TYPE_P (CP_DECL_CONTEXT (t)))
-         ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
-                                 complain,
-                                 in_decl, /*entering_scope=*/1);
-       else if (DECL_NAMESPACE_SCOPE_P (t))
-         ctx = DECL_CONTEXT (t);
+           if (!spec)
+             {
+               tmpl = DECL_TI_TEMPLATE (t);
+               gen_tmpl = most_general_template (tmpl);
+               argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
+               spec = (retrieve_specialization 
+                       (gen_tmpl, argvec,
+                        /*class_specializations_p=*/false));
+             }
+         }
        else
          {
+           /* A local variable.  */
+           local_p = true;
            /* Subsequent calls to pushdecl will fill this in.  */
            ctx = NULL_TREE;
-           local_p = 1;
-         }
-
-       /* Check to see if we already have this specialization.  */
-       if (!local_p)
-         {
-           tmpl = DECL_TI_TEMPLATE (t);
-           gen_tmpl = most_general_template (tmpl);
-           argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
-           spec = retrieve_specialization (gen_tmpl, argvec,
-                                           /*class_specializations_p=*/false);
+           spec = retrieve_local_specialization (t);
          }
-       else
-         spec = retrieve_local_specialization (t);
-
+       /* If we already have the specialization we need, there is
+          nothing more to do.  */ 
        if (spec)
          {
            r = spec;
            break;
          }
 
+       /* Create a new node for the specialization we need.  */
        r = copy_decl (t);
        if (TREE_CODE (r) == VAR_DECL)
          {
@@ -6741,7 +6895,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            if (DECL_HAS_VALUE_EXPR_P (t))
              {
                tree ve = DECL_VALUE_EXPR (t);
-               ve = tsubst_expr (ve, args, complain, in_decl);
+               ve = tsubst_expr (ve, args, complain, in_decl,
+                                 /*constant_expression_p=*/false);
                SET_DECL_VALUE_EXPR (r, ve);
              }
          }
@@ -6760,6 +6915,18 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
          SET_DECL_RTL (r, NULL_RTX);
        DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
+       if (TREE_CODE (r) == VAR_DECL)
+         {
+           /* Possibly limit visibility based on template args.  */
+           DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
+           if (DECL_VISIBILITY_SPECIFIED (t))
+             {
+               DECL_VISIBILITY_SPECIFIED (r) = 0;
+               DECL_ATTRIBUTES (r)
+                 = remove_attribute ("visibility", DECL_ATTRIBUTES (r));
+             }
+           determine_visibility (r);
+         }
 
        if (!local_p)
          {
@@ -7049,11 +7216,20 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       {
        tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
 
-       /* The array dimension behaves like a non-type template arg,
-          in that we want to fold it as much as possible.  */
-       max = tsubst_template_arg (omax, args, complain, in_decl);
+       max = tsubst_expr (omax, args, complain, in_decl,
+                          /*integral_constant_expression_p=*/false);
+       max = fold_non_dependent_expr (max);
        max = fold_decl_constant_value (max);
 
+       if (TREE_CODE (max) != INTEGER_CST 
+           && TREE_CODE (max) != TEMPLATE_PARM_INDEX
+           && !at_function_scope_p ())
+         {
+           if (complain & tf_error)
+             error ("array bound is not an integer constant");
+           return error_mark_node;
+         }
+
        /* [temp.deduct]
 
           Type deduction may fail for any of the following
@@ -7066,7 +7242,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
             indicated by the state of complain), so that
             another substitution can be found.  */
          return error_mark_node;
-
        else if (TREE_CODE (max) == INTEGER_CST
                 && INT_CST_LT (max, integer_zero_node))
          {
@@ -7115,10 +7290,20 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          {
            if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
              {
+               int quals;
                gcc_assert (TYPE_P (arg));
+
+               /* cv-quals from the template are discarded when
+                  substituting in a function or reference type.  */
+               if (TREE_CODE (arg) == FUNCTION_TYPE
+                   || TREE_CODE (arg) == METHOD_TYPE
+                   || TREE_CODE (arg) == REFERENCE_TYPE)
+                 quals = cp_type_quals (arg);
+               else
+                 quals = cp_type_quals (arg) | cp_type_quals (t);
+                 
                return cp_build_qualified_type_real
-                 (arg, cp_type_quals (arg) | cp_type_quals (t),
-                  complain | tf_ignore_bad_quals);
+                 (arg, quals, complain | tf_ignore_bad_quals);
              }
            else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
              {
@@ -7525,7 +7710,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case ARRAY_REF:
       {
        tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
-       tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl);
+       tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl,
+                              /*integral_constant_expression_p=*/false);
        if (e1 == error_mark_node || e2 == error_mark_node)
          return error_mark_node;
 
@@ -7547,8 +7733,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       {
        tree type;
 
-       type = finish_typeof (tsubst_expr (TYPEOF_TYPE_EXPR (t), args,
-                                          complain, in_decl));
+       type = finish_typeof (tsubst_expr 
+                             (TYPEOF_TYPE_EXPR (t), args,
+                              complain, in_decl,
+                              /*integral_constant_expression_p=*/false));
        return cp_build_qualified_type_real (type,
                                             cp_type_quals (t)
                                             | cp_type_quals (type),
@@ -7573,6 +7761,7 @@ tsubst_baselink (tree baselink, tree object_type,
     tree name;
     tree qualifying_scope;
     tree fns;
+    tree optype;
     tree template_args = 0;
     bool template_id_p = false;
 
@@ -7586,6 +7775,7 @@ tsubst_baselink (tree baselink, tree object_type,
        ambiguous now.  Therefore, we perform the lookup again.  */
     qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (baselink));
     fns = BASELINK_FUNCTIONS (baselink);
+    optype = BASELINK_OPTYPE (baselink);
     if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
       {
        template_id_p = true;
@@ -7613,6 +7803,9 @@ tsubst_baselink (tree baselink, tree object_type,
        = build_nt (TEMPLATE_ID_EXPR,
                    BASELINK_FUNCTIONS (baselink),
                    template_args);
+    /* Update the conversion operator type.  */
+    BASELINK_OPTYPE (baselink) 
+      = tsubst (optype, args, complain, in_decl);
 
     if (!object_type)
       object_type = current_class_type;
@@ -7729,7 +7922,11 @@ tsubst_qualified_id (tree qualified_id, tree args,
               /*template_arg_p=*/false));
     }
 
-  if (TREE_CODE (expr) != SCOPE_REF)
+  /* Expressions do not generally have reference type.  */
+  if (TREE_CODE (expr) != SCOPE_REF
+      /* However, if we're about to form a pointer-to-member, we just
+        want the referenced member referenced.  */
+      && TREE_CODE (expr) != OFFSET_REF)
     expr = convert_from_reference (expr);
 
   return expr;
@@ -8138,7 +8335,8 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
        case OMP_CLAUSE_NUM_THREADS:
        case OMP_CLAUSE_SCHEDULE:
          OMP_CLAUSE_OPERAND (nc, 0)
-           = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl);
+           = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, 
+                          in_decl, /*integral_constant_expression_p=*/false);
          break;
        case OMP_CLAUSE_NOWAIT:
        case OMP_CLAUSE_ORDERED:
@@ -8167,7 +8365,8 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
 
   if (TREE_CODE (t) != TREE_LIST)
     return tsubst_copy_and_build (t, args, complain, in_decl,
-                                 /*function_p=*/false);
+                                 /*function_p=*/false,
+                                 /*integral_constant_expression_p=*/false);
 
   if (t == void_list_node)
     return t;
@@ -8189,8 +8388,13 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
    processing.  */
 
 static tree
-tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
+tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
+            bool integral_constant_expression_p)
 {
+#define RECUR(NODE)                            \
+  tsubst_expr ((NODE), args, complain, in_decl,        \
+              integral_constant_expression_p)
+
   tree stmt, tmp;
 
   if (t == NULL_TREE || t == error_mark_node)
@@ -8207,7 +8411,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       {
        tree_stmt_iterator i;
        for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
-         tsubst_expr (tsi_stmt (i), args, complain, in_decl);
+         RECUR (tsi_stmt (i));
        break;
       }
 
@@ -8217,12 +8421,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       break;
 
     case RETURN_EXPR:
-      finish_return_stmt (tsubst_expr (TREE_OPERAND (t, 0),
-                                      args, complain, in_decl));
+      finish_return_stmt (RECUR (TREE_OPERAND (t, 0)));
       break;
 
     case EXPR_STMT:
-      tmp = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl);
+      tmp = RECUR (EXPR_STMT_EXPR (t));
       if (EXPR_STMT_STMT_EXPR_RESULT (t))
        finish_stmt_expr_expr (tmp, cur_stmt_expr);
       else
@@ -8230,8 +8433,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       break;
 
     case USING_STMT:
-      do_using_directive (tsubst_expr (USING_STMT_NAMESPACE (t),
-                                      args, complain, in_decl));
+      do_using_directive (RECUR (USING_STMT_NAMESPACE (t)));
       break;
 
     case DECL_EXPR:
@@ -8248,7 +8450,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
            tree name = DECL_NAME (decl);
            tree decl;
 
-           scope = tsubst_expr (scope, args, complain, in_decl);
+           scope = RECUR (scope);
            decl = lookup_qualified_name (scope, name,
                                          /*is_type_p=*/false,
                                          /*complain=*/false);
@@ -8287,7 +8489,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                        init = cp_fname_init (name, &TREE_TYPE (decl));
                      }
                    else
-                     init = tsubst_expr (init, args, complain, in_decl);
+                     init = RECUR (init);
                    finish_decl (decl, init, NULL_TREE);
                  }
              }
@@ -8300,43 +8502,43 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
     case FOR_STMT:
       stmt = begin_for_stmt ();
-      tsubst_expr (FOR_INIT_STMT (t), args, complain, in_decl);
+                         RECUR (FOR_INIT_STMT (t));
       finish_for_init_stmt (stmt);
-      tmp = tsubst_expr (FOR_COND (t), args, complain, in_decl);
+      tmp = RECUR (FOR_COND (t));
       finish_for_cond (tmp, stmt);
-      tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
+      tmp = RECUR (FOR_EXPR (t));
       finish_for_expr (tmp, stmt);
-      tsubst_expr (FOR_BODY (t), args, complain, in_decl);
+      RECUR (FOR_BODY (t));
       finish_for_stmt (stmt);
       break;
 
     case WHILE_STMT:
       stmt = begin_while_stmt ();
-      tmp = tsubst_expr (WHILE_COND (t), args, complain, in_decl);
+      tmp = RECUR (WHILE_COND (t));
       finish_while_stmt_cond (tmp, stmt);
-      tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
+      RECUR (WHILE_BODY (t));
       finish_while_stmt (stmt);
       break;
 
     case DO_STMT:
       stmt = begin_do_stmt ();
-      tsubst_expr (DO_BODY (t), args, complain, in_decl);
+      RECUR (DO_BODY (t));
       finish_do_body (stmt);
-      tmp = tsubst_expr (DO_COND (t), args, complain, in_decl);
+      tmp = RECUR (DO_COND (t));
       finish_do_stmt (tmp, stmt);
       break;
 
     case IF_STMT:
       stmt = begin_if_stmt ();
-      tmp = tsubst_expr (IF_COND (t), args, complain, in_decl);
+      tmp = RECUR (IF_COND (t));
       finish_if_stmt_cond (tmp, stmt);
-      tsubst_expr (THEN_CLAUSE (t), args, complain, in_decl);
+      RECUR (THEN_CLAUSE (t));
       finish_then_clause (stmt);
 
       if (ELSE_CLAUSE (t))
        {
          begin_else_clause (stmt);
-         tsubst_expr (ELSE_CLAUSE (t), args, complain, in_decl);
+         RECUR (ELSE_CLAUSE (t));
          finish_else_clause (stmt);
        }
 
@@ -8350,7 +8552,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        stmt = begin_compound_stmt (BIND_EXPR_TRY_BLOCK (t)
                                    ? BCS_TRY_BLOCK : 0);
 
-      tsubst_expr (BIND_EXPR_BODY (t), args, complain, in_decl);
+      RECUR (BIND_EXPR_BODY (t));
 
       if (BIND_EXPR_BODY_BLOCK (t))
        finish_function_body (stmt);
@@ -8368,16 +8570,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
     case SWITCH_STMT:
       stmt = begin_switch_stmt ();
-      tmp = tsubst_expr (SWITCH_STMT_COND (t), args, complain, in_decl);
+      tmp = RECUR (SWITCH_STMT_COND (t));
       finish_switch_cond (tmp, stmt);
-      tsubst_expr (SWITCH_STMT_BODY (t), args, complain, in_decl);
+      RECUR (SWITCH_STMT_BODY (t));
       finish_switch_stmt (stmt);
       break;
 
     case CASE_LABEL_EXPR:
-      finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl),
-                        tsubst_expr (CASE_HIGH (t), args, complain,
-                                     in_decl));
+      finish_case_label (RECUR (CASE_LOW (t)),
+                        RECUR (CASE_HIGH (t)));
       break;
 
     case LABEL_EXPR:
@@ -8390,7 +8591,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        /* Computed goto's must be tsubst'd into.  On the other hand,
           non-computed gotos must not be; the identifier in question
           will have no binding.  */
-       tmp = tsubst_expr (tmp, args, complain, in_decl);
+       tmp = RECUR (tmp);
       else
        tmp = DECL_NAME (tmp);
       finish_goto_stmt (tmp);
@@ -8399,7 +8600,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case ASM_EXPR:
       tmp = finish_asm_stmt
        (ASM_VOLATILE_P (t),
-        tsubst_expr (ASM_STRING (t), args, complain, in_decl),
+        RECUR (ASM_STRING (t)),
         tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl),
         tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl),
         tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl));
@@ -8415,11 +8616,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       if (CLEANUP_P (t))
        {
          stmt = begin_try_block ();
-         tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
+         RECUR (TRY_STMTS (t));
          finish_cleanup_try_block (stmt);
-         finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args,
-                                      complain, in_decl),
-                         stmt);
+         finish_cleanup (RECUR (TRY_HANDLERS (t)), stmt);
        }
       else
        {
@@ -8430,14 +8629,14 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          else
            stmt = begin_try_block ();
 
-         tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
+         RECUR (TRY_STMTS (t));
 
          if (FN_TRY_BLOCK_P (t))
            finish_function_try_block (stmt);
          else
            finish_try_block (stmt);
 
-         tsubst_expr (TRY_HANDLERS (t), args, complain, in_decl);
+         RECUR (TRY_HANDLERS (t));
          if (FN_TRY_BLOCK_P (t))
            finish_function_handler_sequence (stmt, compound_stmt);
          else
@@ -8447,22 +8646,20 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
     case HANDLER:
       {
-       tree decl;
+       tree decl = HANDLER_PARMS (t);
 
-       stmt = begin_handler ();
-       if (HANDLER_PARMS (t))
+       if (decl)
          {
-           decl = HANDLER_PARMS (t);
            decl = tsubst (decl, args, complain, in_decl);
            /* Prevent instantiate_decl from trying to instantiate
               this variable.  We've already done all that needs to be
               done.  */
-           DECL_TEMPLATE_INSTANTIATED (decl) = 1;
+           if (decl != error_mark_node)
+             DECL_TEMPLATE_INSTANTIATED (decl) = 1;
          }
-       else
-         decl = NULL_TREE;
+       stmt = begin_handler ();
        finish_handler_parms (decl, stmt);
-       tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
+       RECUR (HANDLER_BODY (t));
        finish_handler (stmt);
       }
       break;
@@ -8475,7 +8672,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
                                args, complain, in_decl);
       stmt = begin_omp_parallel ();
-      tsubst_expr (OMP_PARALLEL_BODY (t), args, complain, in_decl);
+      RECUR (OMP_PARALLEL_BODY (t));
       OMP_PARALLEL_COMBINED (finish_omp_parallel (tmp, stmt))
        = OMP_PARALLEL_COMBINED (t);
       break;
@@ -8488,19 +8685,19 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                                      args, complain, in_decl);
        init = OMP_FOR_INIT (t);
        gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
-       decl = tsubst_expr (TREE_OPERAND (init, 0), args, complain, in_decl);
-       init = tsubst_expr (TREE_OPERAND (init, 1), args, complain, in_decl);
-       cond = tsubst_expr (OMP_FOR_COND (t), args, complain, in_decl);
-       incr = tsubst_expr (OMP_FOR_INCR (t), args, complain, in_decl);
+       decl = RECUR (TREE_OPERAND (init, 0));
+       init = RECUR (TREE_OPERAND (init, 1));
+       cond = RECUR (OMP_FOR_COND (t));
+       incr = RECUR (OMP_FOR_INCR (t));
 
        stmt = begin_omp_structured_block ();
 
        pre_body = push_stmt_list ();
-       tsubst_expr (OMP_FOR_PRE_BODY (t), args, complain, in_decl);
+       RECUR (OMP_FOR_PRE_BODY (t));
        pre_body = pop_stmt_list (pre_body);
 
        body = push_stmt_list ();
-       tsubst_expr (OMP_FOR_BODY (t), args, complain, in_decl);
+       RECUR (OMP_FOR_BODY (t));
        body = pop_stmt_list (body);
 
        t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
@@ -8516,7 +8713,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case OMP_SINGLE:
       tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl);
       stmt = push_stmt_list ();
-      tsubst_expr (OMP_BODY (t), args, complain, in_decl);
+      RECUR (OMP_BODY (t));
       stmt = pop_stmt_list (stmt);
 
       t = copy_node (t);
@@ -8530,7 +8727,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case OMP_MASTER:
     case OMP_ORDERED:
       stmt = push_stmt_list ();
-      tsubst_expr (OMP_BODY (t), args, complain, in_decl);
+      RECUR (OMP_BODY (t));
       stmt = pop_stmt_list (stmt);
 
       t = copy_node (t);
@@ -8541,8 +8738,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case OMP_ATOMIC:
       {
        tree op0, op1;
-       op0 = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl);
-       op1 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl);
+       op0 = RECUR (TREE_OPERAND (t, 0));
+       op1 = RECUR (TREE_OPERAND (t, 1));
        finish_omp_atomic (OMP_ATOMIC_CODE (t), op0, op1);
       }
       break;
@@ -8551,10 +8748,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
 
       return tsubst_copy_and_build (t, args, complain, in_decl,
-                                   /*function_p=*/false);
+                                   /*function_p=*/false,
+                                   integral_constant_expression_p);
     }
 
   return NULL_TREE;
+#undef RECUR
 }
 
 /* T is a postfix-expression that is not being used in a function
@@ -8570,7 +8769,8 @@ tsubst_non_call_postfix_expression (tree t, tree args,
                             /*done=*/false, /*address_p=*/false);
   else
     t = tsubst_copy_and_build (t, args, complain, in_decl,
-                              /*function_p=*/false);
+                              /*function_p=*/false,
+                              /*integral_constant_expression_p=*/false);
 
   return t;
 }
@@ -8583,10 +8783,13 @@ tsubst_copy_and_build (tree t,
                       tree args,
                       tsubst_flags_t complain,
                       tree in_decl,
-                      bool function_p)
+                      bool function_p,
+                      bool integral_constant_expression_p)
 {
-#define RECUR(NODE) \
-  tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false)
+#define RECUR(NODE)                                            \
+  tsubst_copy_and_build (NODE, args, complain, in_decl,        \
+                        /*function_p=*/false,                  \
+                        integral_constant_expression_p)
 
   tree op1;
 
@@ -8621,7 +8824,7 @@ tsubst_copy_and_build (tree t,
 
        decl = finish_id_expression (t, decl, NULL_TREE,
                                     &idk,
-                                    /*integral_constant_expression_p=*/false,
+                                    integral_constant_expression_p,
                                     /*allow_non_integral_constant_expression_p=*/false,
                                     &non_integral_constant_expression_p,
                                     /*template_p=*/false,
@@ -8658,7 +8861,7 @@ tsubst_copy_and_build (tree t,
          return build3 (COMPONENT_REF, TREE_TYPE (template),
                         object, template, NULL_TREE);
        else
-         return template;
+         return baselink_for_fns (template);
       }
 
     case INDIRECT_REF:
@@ -8684,29 +8887,41 @@ tsubst_copy_and_build (tree t,
         RECUR (TREE_OPERAND (t, 0)));
 
     case CAST_EXPR:
-      return build_functional_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
-
     case REINTERPRET_CAST_EXPR:
-      return build_reinterpret_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
-
     case CONST_CAST_EXPR:
-      return build_const_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
-
     case DYNAMIC_CAST_EXPR:
-      return build_dynamic_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
-
     case STATIC_CAST_EXPR:
-      return build_static_cast
-       (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        RECUR (TREE_OPERAND (t, 0)));
+      {
+       tree type;
+       tree op;
+
+       type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+       if (integral_constant_expression_p
+           && !cast_valid_in_integral_constant_expression_p (type))
+         {
+           error ("a cast to a type other than an integral or "
+                  "enumeration type cannot appear in a constant-expression");
+           return error_mark_node; 
+         }
+
+       op = RECUR (TREE_OPERAND (t, 0));
+
+       switch (TREE_CODE (t))
+         {
+         case CAST_EXPR:
+           return build_functional_cast (type, op);
+         case REINTERPRET_CAST_EXPR:
+           return build_reinterpret_cast (type, op);
+         case CONST_CAST_EXPR:
+           return build_const_cast (type, op);
+         case DYNAMIC_CAST_EXPR:
+           return build_dynamic_cast (type, op);
+         case STATIC_CAST_EXPR:
+           return build_static_cast (type, op);
+         default:
+           gcc_unreachable ();
+         }
+      }
 
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
@@ -8797,7 +9012,9 @@ tsubst_copy_and_build (tree t,
       else
        {
          ++skip_evaluation;
-         op1 = RECUR (op1);
+         op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+                                      /*function_p=*/false,
+                                      /*integral_constant_expression_p=*/false);
          --skip_evaluation;
        }
       if (TYPE_P (op1))
@@ -8882,7 +9099,9 @@ tsubst_copy_and_build (tree t,
 
            function = tsubst_copy_and_build (function, args, complain,
                                              in_decl,
-                                             !qualified_p);
+                                             !qualified_p,
+                                             integral_constant_expression_p);
+
            if (BASELINK_P (function))
              qualified_p = true;
          }
@@ -9065,6 +9284,9 @@ tsubst_copy_and_build (tree t,
        tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
        bool process_index_p;
 
+       if (type == error_mark_node)
+         return error_mark_node;
+
        /* digest_init will do the wrong thing if we let it.  */
        if (type && TYPE_PTRMEMFUNC_P (type))
          return t;
@@ -9128,7 +9350,8 @@ tsubst_copy_and_build (tree t,
        tree stmt_expr = begin_stmt_expr ();
 
        cur_stmt_expr = stmt_expr;
-       tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
+       tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl,
+                    integral_constant_expression_p);
        stmt_expr = finish_stmt_expr (stmt_expr, false);
        cur_stmt_expr = old_stmt_expr;
 
@@ -9140,7 +9363,10 @@ tsubst_copy_and_build (tree t,
       /* As in finish_id_expression, we resolve enumeration constants
         to their underlying values.  */
       if (TREE_CODE (t) == CONST_DECL)
-       return DECL_INITIAL (t);
+       {
+         used_types_insert (TREE_TYPE (t));
+         return DECL_INITIAL (t);
+       }
       return t;
 
     default:
@@ -9680,7 +9906,12 @@ type_unification_real (tree tparms,
     for (i = 0; i < ntparms; i++)
       if (!TREE_VEC_ELT (targs, i))
        {
-         tree tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
+         tree tparm;
+
+          if (TREE_VEC_ELT (tparms, i) == error_mark_node)
+            continue;
+
+          tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
 
          /* If this is an undeduced nontype parameter that depends on
             a type parameter, try another pass; its type may have been
@@ -10387,21 +10618,56 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
        {
          tree parm_max;
          tree arg_max;
-
-         parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
-         arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
+         bool parm_cst;
+         bool arg_cst;
 
          /* Our representation of array types uses "N - 1" as the
             TYPE_MAX_VALUE for an array with "N" elements, if "N" is
-            not an integer constant.  */
-         if (TREE_CODE (parm_max) == MINUS_EXPR)
+            not an integer constant.  We cannot unify arbitrarily
+            complex expressions, so we eliminate the MINUS_EXPRs
+            here.  */
+         parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
+         parm_cst = TREE_CODE (parm_max) == INTEGER_CST;
+         if (!parm_cst)
            {
-             arg_max = fold_build2 (PLUS_EXPR,
-                                    integer_type_node,
-                                    arg_max,
-                                    TREE_OPERAND (parm_max, 1));
+             gcc_assert (TREE_CODE (parm_max) == MINUS_EXPR);
              parm_max = TREE_OPERAND (parm_max, 0);
            }
+         arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
+         arg_cst = TREE_CODE (arg_max) == INTEGER_CST;
+         if (!arg_cst)
+           {
+             /* The ARG_MAX may not be a simple MINUS_EXPR, if we are
+                trying to unify the type of a variable with the type
+                of a template parameter.  For example:
+
+                   template <unsigned int N>
+                  void f (char (&) [N]);
+                  int g(); 
+                  void h(int i) {
+                     char a[g(i)];
+                    f(a); 
+                   }
+
+                Here, the type of the ARG will be "int [g(i)]", and
+                may be a SAVE_EXPR, etc.  */
+             if (TREE_CODE (arg_max) != MINUS_EXPR)
+               return 1;
+             arg_max = TREE_OPERAND (arg_max, 0);
+           }
+
+         /* If only one of the bounds used a MINUS_EXPR, compensate
+            by adding one to the other bound.  */
+         if (parm_cst && !arg_cst)
+           parm_max = fold_build2 (PLUS_EXPR,
+                                   integer_type_node,
+                                   parm_max,
+                                   integer_one_node);
+         else if (arg_cst && !parm_cst)
+           arg_max = fold_build2 (PLUS_EXPR,
+                                  integer_type_node,
+                                  arg_max,
+                                  integer_one_node);
 
          if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
            return 1;
@@ -11604,7 +11870,8 @@ regenerate_decl_from_template (tree decl, tree tmpl)
   else if (TREE_CODE (decl) == VAR_DECL)
     DECL_INITIAL (decl) =
       tsubst_expr (DECL_INITIAL (code_pattern), args,
-                  tf_error, DECL_TI_TEMPLATE (decl));
+                  tf_error, DECL_TI_TEMPLATE (decl),
+                  /*integral_constant_expression_p=*/false);
   else
     gcc_unreachable ();
 
@@ -11853,7 +12120,8 @@ instantiate_decl (tree d, int defer_ok,
          push_nested_class (DECL_CONTEXT (d));
          init = tsubst_expr (DECL_INITIAL (code_pattern),
                              args,
-                             tf_warning_or_error, NULL_TREE);
+                             tf_warning_or_error, NULL_TREE,
+                             /*integral_constant_expression_p=*/false);
          cp_finish_decl (d, init, /*init_const_expr_p=*/false,
                          /*asmspec_tree=*/NULL_TREE,
                          LOOKUP_ONLYCONVERTING);
@@ -11984,7 +12252,8 @@ instantiate_decl (tree d, int defer_ok,
 
       /* Substitute into the body of the function.  */
       tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
-                  tf_warning_or_error, tmpl);
+                  tf_warning_or_error, tmpl,
+                  /*integral_constant_expression_p=*/false);
 
       /* We don't need the local specializations any more.  */
       htab_delete (local_specializations);
@@ -12138,7 +12407,8 @@ tsubst_initializer_list (tree t, tree argvec)
        in_base_initializer = 1;
 
       init = tsubst_expr (TREE_VALUE (t), argvec, tf_warning_or_error,
-                         NULL_TREE);
+                         NULL_TREE, 
+                         /*integral_constant_expression_p=*/false);
       in_base_initializer = 0;
 
       if (decl)
@@ -12182,7 +12452,8 @@ tsubst_enum (tree tag, tree newtag, tree args)
       /* Note that in a template enum, the TREE_VALUE is the
         CONST_DECL, not the corresponding INTEGER_CST.  */
       value = tsubst_expr (DECL_INITIAL (decl),
-                          args, tf_warning_or_error, NULL_TREE);
+                          args, tf_warning_or_error, NULL_TREE,
+                          /*integral_constant_expression_p=*/true);
 
       /* Give this enumeration constant the correct access.  */
       set_current_access_from_decl (decl);
@@ -12630,7 +12901,8 @@ type_dependent_expression_p (tree expression)
     return false;
 
   /* An unresolved name is always dependent.  */
-  if (TREE_CODE (expression) == IDENTIFIER_NODE)
+  if (TREE_CODE (expression) == IDENTIFIER_NODE
+      || TREE_CODE (expression) == USING_DECL)
     return true;
 
   /* Some expression forms are never type-dependent.  */