OSDN Git Service

PR c++/52824
[pf3gnuchains/gcc-fork.git] / gcc / cp / pt.c
index 2ba26b2..185212d 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, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
    Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
    Rewritten by Jason Merrill (jason@cygnus.com).
@@ -2976,6 +2976,20 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
     (struct find_parameter_pack_data*)data;
   bool parameter_pack_p = false;
 
+  /* Handle type aliases/typedefs.  */
+  if (TYPE_P (t)
+      && TYPE_NAME (t)
+      && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
+      && TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
+    {
+      if (TYPE_TEMPLATE_INFO (t))
+       cp_walk_tree (&TYPE_TI_ARGS (t),
+                     &find_parameter_packs_r,
+                     ppd, ppd->visited);
+      *walk_subtrees = 0;
+      return NULL_TREE;
+    }
+
   /* Identify whether this is a parameter pack or not.  */
   switch (TREE_CODE (t))
     {
@@ -3224,6 +3238,8 @@ make_pack_expansion (tree arg)
     }
   PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs;
 
+  PACK_EXPANSION_LOCAL_P (result) = at_function_scope_p ();
+
   return result;
 }
 
@@ -4905,7 +4921,10 @@ push_template_decl_real (tree decl, bool is_friend)
       if (check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type)))
        TYPE_RAISES_EXCEPTIONS (type) = NULL_TREE;
     }
-  else if (check_for_bare_parameter_packs (TREE_TYPE (decl)))
+  else if (check_for_bare_parameter_packs ((TREE_CODE (decl) == TYPE_DECL
+                                           && TYPE_DECL_ALIAS_P (decl))
+                                          ? DECL_ORIGINAL_TYPE (decl)
+                                          : TREE_TYPE (decl)))
     {
       TREE_TYPE (decl) = error_mark_node;
       return error_mark_node;
@@ -5501,9 +5520,16 @@ static int
 unify_inconsistency (bool explain_p, tree parm, tree first, tree second)
 {
   if (explain_p)
-    inform (input_location,
-           "  conflicting deductions for parameter %qE (%qE and %qE)",
-           parm, first, second);
+    {
+      if (TYPE_P (parm))
+       inform (input_location,
+               "  deduced conflicting types for parameter %qT (%qT and %qT)",
+               parm, first, second);
+      else
+       inform (input_location,
+               "  deduced conflicting values for non-type parameter "
+               "%qE (%qE and %qE)", parm, first, second);
+    }
   return 1;
 }
 
@@ -5696,11 +5722,15 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
      to a null value, but otherwise still need to be of a specific form.  */
   if (cxx_dialect >= cxx0x)
     {
-      if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+      if (TREE_CODE (expr) == PTRMEM_CST)
+       /* A PTRMEM_CST is already constant, and a valid template
+          argument for a parameter of pointer to member type, we just want
+          to leave it in that form rather than lower it to a
+          CONSTRUCTOR.  */;
+      else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
        expr = maybe_constant_value (expr);
       else if (TYPE_PTR_P (type)
-              || (TYPE_PTR_TO_MEMBER_P (type)
-                  && TREE_CODE (expr) != PTRMEM_CST))
+              || TYPE_PTR_TO_MEMBER_P (type))
        {
          tree folded = maybe_constant_value (expr);
          if (TYPE_PTR_P (type) ? integer_zerop (folded)
@@ -5779,6 +5809,9 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
          if (complain & tf_error)
            {
              int errs = errorcount, warns = warningcount;
+             if (processing_template_decl
+                 && !require_potential_constant_expression (expr))
+               return NULL_TREE;
              expr = cxx_constant_value (expr);
              if (errorcount > errs || warningcount > warns)
                inform (EXPR_LOC_OR_HERE (expr),
@@ -6417,8 +6450,16 @@ convert_template_argument (tree parm,
   if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
       && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
     {
-      permerror (input_location, "to refer to a type member of a template parameter, "
-                "use %<typename %E%>", orig_arg);
+      if (TREE_CODE (TREE_OPERAND (arg, 1)) == BIT_NOT_EXPR)
+       {
+         if (complain & tf_error)
+           error ("invalid use of destructor %qE as a type", orig_arg);
+         return error_mark_node;
+       }
+
+      permerror (input_location,
+                "to refer to a type member of a template parameter, "
+                "use %<typename %E%>", orig_arg);
 
       orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
                                     TREE_OPERAND (arg, 1),
@@ -6693,6 +6734,20 @@ coerce_template_parameter_pack (tree parms,
   return argument_pack;
 }
 
+/* Returns true if the template argument vector ARGS contains
+   any pack expansions, false otherwise.  */
+
+static bool
+any_pack_expanson_args_p (tree args)
+{
+  int i;
+  if (args)
+    for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
+      if (PACK_EXPANSION_P (TREE_VEC_ELT (args, i)))
+       return true;
+  return false;
+}
+
 /* Convert all template arguments to their appropriate types, and
    return a vector containing the innermost resulting template
    arguments.  If any error occurs, return error_mark_node. Error and
@@ -6758,6 +6813,7 @@ coerce_template_parms (tree parms,
   if ((nargs > nparms && !variadic_p)
       || (nargs < nparms - variadic_p
          && require_all_args
+         && !any_pack_expanson_args_p (inner_args)
          && (!use_default_args
              || (TREE_VEC_ELT (parms, nargs) != error_mark_node
                   && !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs))))))
@@ -7427,6 +7483,9 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 
       context = tsubst (DECL_CONTEXT (gen_tmpl), arglist,
                        complain, in_decl);
+      if (context == error_mark_node)
+       return error_mark_node;
+
       if (!context)
        context = global_namespace;
 
@@ -8115,6 +8174,9 @@ parameter_of_template_p (tree parm, tree templ)
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
     {
       tree p = TREE_VALUE (TREE_VEC_ELT (parms, i));
+      if (p == error_mark_node)
+       continue;
+
       if (parm == p
          || (DECL_INITIAL (parm)
              && DECL_INITIAL (parm) == DECL_INITIAL (p)))
@@ -9103,14 +9165,20 @@ instantiate_class_template_1 (tree type)
 
   if (CLASSTYPE_LAMBDA_EXPR (type))
     {
-      tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
-      if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
+      tree decl = lambda_function (type);
+      if (decl)
        {
-         apply_lambda_return_type (lambda, void_type_node);
-         LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
+         tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
+         if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
+           {
+             apply_lambda_return_type (lambda, void_type_node);
+             LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
+           }
+         instantiate_decl (decl, false, false);
+         maybe_add_lambda_conv_op (type);
        }
-      instantiate_decl (lambda_function (type), false, false);
-      maybe_add_lambda_conv_op (type);
+      else
+       gcc_assert (errorcount);
     }
 
   /* Set the file and line number information to whatever is given for
@@ -9255,6 +9323,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   int i, len = -1;
   tree result;
   htab_t saved_local_specializations = NULL;
+  bool need_local_specializations = false;
   int levels;
 
   gcc_assert (PACK_EXPANSION_P (t));
@@ -9288,7 +9357,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
        }
       if (TREE_CODE (parm_pack) == PARM_DECL)
        {
-         if (!cp_unevaluated_operand)
+         if (PACK_EXPANSION_LOCAL_P (t))
            arg_pack = retrieve_local_specialization (parm_pack);
          else
            {
@@ -9304,6 +9373,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
                arg_pack = NULL_TREE;
              else
                arg_pack = make_fnparm_pack (arg_pack);
+             need_local_specializations = true;
            }
        }
       else
@@ -9434,7 +9504,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   if (len < 0)
     return error_mark_node;
 
-  if (cp_unevaluated_operand)
+  if (need_local_specializations)
     {
       /* We're in a late-specified return type, so create our own local
         specializations table; the current table is either NULL or (in the
@@ -9529,7 +9599,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
         }
     }
 
-  if (saved_local_specializations)
+  if (need_local_specializations)
     {
       htab_delete (local_specializations);
       local_specializations = saved_local_specializations;
@@ -10609,7 +10679,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
              type = DECL_ORIGINAL_TYPE (t);
            else
              type = TREE_TYPE (t);
-           if (TREE_CODE (t) == VAR_DECL && VAR_HAD_UNKNOWN_BOUND (t))
+           if (TREE_CODE (t) == VAR_DECL
+               && VAR_HAD_UNKNOWN_BOUND (t)
+               && type != error_mark_node)
              type = strip_array_domain (type);
            type = tsubst (type, args, complain, in_decl);
          }
@@ -11121,7 +11193,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
             complain | tf_ignore_bad_quals);
          return r;
        }
-      /* Else we must be instantiating the typedef, so fall through.  */
+      else
+       /* We don't have an instantiation yet, so drop the typedef.  */
+       t = DECL_ORIGINAL_TYPE (decl);
     }
 
   if (type
@@ -11799,6 +11873,7 @@ tsubst_baselink (tree baselink, tree object_type,
     tree optype;
     tree template_args = 0;
     bool template_id_p = false;
+    bool qualified = BASELINK_QUALIFIED_P (baselink);
 
     /* A baselink indicates a function from a base class.  Both the
        BASELINK_ACCESS_BINFO and the base class referenced may
@@ -11847,9 +11922,12 @@ tsubst_baselink (tree baselink, tree object_type,
 
     if (!object_type)
       object_type = current_class_type;
-    return adjust_result_of_qualified_name_lookup (baselink,
-                                                  qualifying_scope,
-                                                  object_type);
+
+    if (qualified)
+      baselink = adjust_result_of_qualified_name_lookup (baselink,
+                                                        qualifying_scope,
+                                                        object_type);
+    return baselink;
 }
 
 /* Like tsubst_expr for a SCOPE_REF, given by QUALIFIED_ID.  DONE is
@@ -12553,8 +12631,17 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
   if (purpose)
     purpose = RECUR (purpose);
   value = TREE_VALUE (t);
-  if (value && TREE_CODE (value) != LABEL_DECL)
-    value = RECUR (value);
+  if (value)
+    {
+      if (TREE_CODE (value) != LABEL_DECL)
+       value = RECUR (value);
+      else
+       {
+         value = lookup_label (DECL_NAME (value));
+         gcc_assert (TREE_CODE (value) == LABEL_DECL);
+         TREE_USED (value) = 1;
+       }
+    }
   chain = TREE_CHAIN (t);
   if (chain && chain != void_type_node)
     chain = RECUR (chain);
@@ -12795,6 +12882,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
                    && ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
                  /* Anonymous aggregates are a special case.  */
                  finish_anon_union (decl);
+               else if (is_capture_proxy (DECL_EXPR_DECL (t)))
+                 {
+                   DECL_CONTEXT (decl) = current_function_decl;
+                   insert_capture_proxy (decl);
+                 }
                else
                  {
                    int const_init = false;
@@ -13209,20 +13301,33 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 
         if (TRANSACTION_EXPR_IS_STMT (t))
           {
+           tree body = TRANSACTION_EXPR_BODY (t);
+           tree noex = NULL_TREE;
+           if (TREE_CODE (body) == MUST_NOT_THROW_EXPR)
+             {
+               noex = MUST_NOT_THROW_COND (body);
+               if (noex == NULL_TREE)
+                 noex = boolean_true_node;
+               body = TREE_OPERAND (body, 0);
+             }
             stmt = begin_transaction_stmt (input_location, NULL, flags);
-            RECUR (TRANSACTION_EXPR_BODY (t));
-            finish_transaction_stmt (stmt, NULL, flags);
+            RECUR (body);
+            finish_transaction_stmt (stmt, NULL, flags, RECUR (noex));
           }
         else
           {
             stmt = build_transaction_expr (EXPR_LOCATION (t),
                                           RECUR (TRANSACTION_EXPR_BODY (t)),
-                                          flags);
+                                          flags, NULL_TREE);
             return stmt;
           }
       }
       break;
 
+    case MUST_NOT_THROW_EXPR:
+      return build_must_not_throw_expr (RECUR (TREE_OPERAND (t, 0)),
+                                       RECUR (MUST_NOT_THROW_COND (t)));
+
     case EXPR_PACK_EXPANSION:
       error ("invalid use of pack expansion expression");
       return error_mark_node;
@@ -13499,18 +13604,23 @@ tsubst_copy_and_build (tree t,
     case GT_EXPR:
     case MEMBER_REF:
     case DOTSTAR_EXPR:
-      return build_x_binary_op
-       (TREE_CODE (t),
-        RECUR (TREE_OPERAND (t, 0)),
-        (TREE_NO_WARNING (TREE_OPERAND (t, 0))
-         ? ERROR_MARK
-         : TREE_CODE (TREE_OPERAND (t, 0))),
-        RECUR (TREE_OPERAND (t, 1)),
-        (TREE_NO_WARNING (TREE_OPERAND (t, 1))
-         ? ERROR_MARK
-         : TREE_CODE (TREE_OPERAND (t, 1))),
-        /*overload=*/NULL,
-        complain);
+      {
+       tree r = build_x_binary_op
+         (TREE_CODE (t),
+          RECUR (TREE_OPERAND (t, 0)),
+          (TREE_NO_WARNING (TREE_OPERAND (t, 0))
+           ? ERROR_MARK
+           : TREE_CODE (TREE_OPERAND (t, 0))),
+          RECUR (TREE_OPERAND (t, 1)),
+          (TREE_NO_WARNING (TREE_OPERAND (t, 1))
+           ? ERROR_MARK
+           : TREE_CODE (TREE_OPERAND (t, 1))),
+          /*overload=*/NULL,
+          complain);
+       if (EXPR_P (r) && TREE_NO_WARNING (t))
+         TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+       return r;
+      }
 
     case SCOPE_REF:
       return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
@@ -14290,6 +14400,10 @@ tsubst_copy_and_build (tree t,
        return r;
       }
 
+    case TRANSACTION_EXPR:
+      return tsubst_expr(t, args, complain, in_decl,
+            integral_constant_expression_p);
+
     default:
       /* Handle Objective-C++ constructs, if appropriate.  */
       {
@@ -14458,7 +14572,6 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
   tree fndecl;
   tree gen_tmpl;
   tree spec;
-  HOST_WIDE_INT saved_processing_template_decl;
 
   if (tmpl == error_mark_node)
     return error_mark_node;
@@ -14519,18 +14632,22 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
      deferring all checks until we have the FUNCTION_DECL.  */
   push_deferring_access_checks (dk_deferred);
 
-  /* Although PROCESSING_TEMPLATE_DECL may be true at this point
-     (because, for example, we have encountered a non-dependent
-     function call in the body of a template function and must now
-     determine which of several overloaded functions will be called),
-     within the instantiation itself we are not processing a
-     template.  */  
-  saved_processing_template_decl = processing_template_decl;
-  processing_template_decl = 0;
+  /* Instantiation of the function happens in the context of the function
+     template, not the context of the overload resolution we're doing.  */
+  push_to_top_level ();
+  if (DECL_CLASS_SCOPE_P (gen_tmpl))
+    {
+      tree ctx = tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
+                        complain, gen_tmpl);
+      push_nested_class (ctx);
+    }
   /* Substitute template parameters to obtain the specialization.  */
   fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
                   targ_ptr, complain, gen_tmpl);
-  processing_template_decl = saved_processing_template_decl;
+  if (DECL_CLASS_SCOPE_P (gen_tmpl))
+    pop_nested_class ();
+  pop_from_top_level ();
+
   if (fndecl == error_mark_node)
     return error_mark_node;
 
@@ -15395,7 +15512,7 @@ resolve_overloaded_unification (tree tparms,
              elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
              if (try_one_overload (tparms, targs, tempargs, parm,
                                    elem, strict, sub_strict, addr_p, explain_p)
-                 && (!goodfn || !decls_match (goodfn, elem)))
+                 && (!goodfn || !same_type_p (goodfn, elem)))
                {
                  goodfn = elem;
                  ++good;
@@ -16196,6 +16313,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
       idx = TEMPLATE_TYPE_IDX (parm);
       targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
       tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
+      if (tparm == error_mark_node)
+       return unify_invalid (explain_p);
 
       /* Check for mixed types and values.  */
       if ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM
@@ -16556,6 +16675,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
     case BOOLEAN_TYPE:
     case ENUMERAL_TYPE:
     case VOID_TYPE:
+    case NULLPTR_TYPE:
       if (TREE_CODE (arg) != TREE_CODE (parm))
        return unify_type_mismatch (explain_p, parm, arg);
 
@@ -16808,7 +16928,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 
     default:
       /* An unresolved overload is a nondeduced context.  */
-      if (type_unknown_p (parm))
+      if (is_overloaded_fn (parm) || type_unknown_p (parm))
        return unify_success (explain_p);
       gcc_assert (EXPR_P (parm));
 
@@ -18817,6 +18937,7 @@ tsubst_initializer_list (tree t, tree argvec)
           /* Build a dummy EXPR_PACK_EXPANSION that will be used to
              expand each argument in the TREE_VALUE of t.  */
           expr = make_node (EXPR_PACK_EXPANSION);
+         PACK_EXPANSION_LOCAL_P (expr) = true;
           PACK_EXPANSION_PARAMETER_PACKS (expr) =
             PACK_EXPANSION_PARAMETER_PACKS (TREE_PURPOSE (t));
 
@@ -18877,6 +18998,7 @@ tsubst_initializer_list (tree t, tree argvec)
             }
           else
             {
+             tree tmp;
               decl = tsubst_copy (TREE_PURPOSE (t), argvec, 
                                   tf_warning_or_error, NULL_TREE);
 
@@ -18885,10 +19007,17 @@ tsubst_initializer_list (tree t, tree argvec)
                 in_base_initializer = 1;
 
              init = TREE_VALUE (t);
+             tmp = init;
              if (init != void_type_node)
                init = tsubst_expr (init, argvec,
                                    tf_warning_or_error, NULL_TREE,
                                    /*integral_constant_expression_p=*/false);
+             if (init == NULL_TREE && tmp != NULL_TREE)
+               /* If we had an initializer but it instantiated to nothing,
+                  value-initialize the object.  This will only occur when
+                  the initializer was a pack expansion where the parameter
+                  packs used in that expansion were of length zero.  */
+               init = void_type_node;
               in_base_initializer = 0;
             }
 
@@ -19447,6 +19576,11 @@ value_dependent_expression_p (tree expression)
        return false;
       }
 
+    case STMT_EXPR:
+      /* Treat a GNU statement expression as dependent to avoid crashing
+        under fold_non_dependent_expr; it can't be constant.  */
+      return true;
+
     default:
       /* A constant expression is value-dependent if any subexpression is
         value-dependent.  */