OSDN Git Service

* pt.c (register_specialization): Push DECL_SOURCE_LOCATION to the
[pf3gnuchains/gcc-fork.git] / gcc / cp / pt.c
index eb43271..6b98956 100644 (file)
@@ -191,6 +191,9 @@ static tree tsubst_decl (tree, tree, tsubst_flags_t);
 static void perform_typedefs_access_check (tree tmpl, tree targs);
 static void append_type_to_template_for_access_check_1 (tree, tree, tree);
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
+static bool primary_template_instantiation_p (const_tree);
+static tree listify (tree);
+static tree listify_autos (tree, tree);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -287,14 +290,17 @@ finish_member_template_decl (tree decl)
 /* Return the template info node corresponding to T, whatever T is.  */
 
 tree
-get_template_info (tree t)
+get_template_info (const_tree t)
 {
   tree tinfo = NULL_TREE;
 
+  if (!t || t == error_mark_node)
+    return NULL;
+
   if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
     tinfo = DECL_TEMPLATE_INFO (t);
 
-  if (!tinfo && TREE_CODE (t) == TYPE_DECL)
+  if (!tinfo && DECL_IMPLICIT_TYPEDEF_P (t))
     t = TREE_TYPE (t);
 
   if (TAGGED_TYPE_P (t))
@@ -1296,7 +1302,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
     {
       if (DECL_TEMPLATE_INSTANTIATION (fn))
        {
-         if (TREE_USED (fn)
+         if (DECL_ODR_USED (fn)
              || DECL_EXPLICIT_INSTANTIATION (fn))
            {
              error ("specialization of %qD after instantiation",
@@ -1342,8 +1348,12 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
                to the primary function; now copy the inline bits to
                the various clones.  */
              FOR_EACH_CLONE (clone, fn)
-               DECL_DECLARED_INLINE_P (clone)
-                 = DECL_DECLARED_INLINE_P (fn);
+               {
+                 DECL_DECLARED_INLINE_P (clone)
+                   = DECL_DECLARED_INLINE_P (fn);
+                 DECL_SOURCE_LOCATION (clone)
+                   = DECL_SOURCE_LOCATION (fn);
+               }
              check_specialization_namespace (fn);
 
              return fn;
@@ -2614,6 +2624,7 @@ comp_template_parms (const_tree parms1, const_tree parms2)
 }
 
 /* Determine whether PARM is a parameter pack.  */
+
 bool 
 template_parameter_pack_p (const_tree parm)
 {
@@ -2632,8 +2643,50 @@ template_parameter_pack_p (const_tree parm)
          && TEMPLATE_TYPE_PARAMETER_PACK (parm));
 }
 
+/* Determine if T is a function parameter pack.  */
+
+bool
+function_parameter_pack_p (const_tree t)
+{
+  if (t && TREE_CODE (t) == PARM_DECL)
+    return FUNCTION_PARAMETER_PACK_P (t);
+  return false;
+}
+
+/* Return the function template declaration of PRIMARY_FUNC_TMPL_INST.
+   PRIMARY_FUNC_TMPL_INST is a primary function template instantiation.  */
+
+tree
+get_function_template_decl (const_tree primary_func_tmpl_inst)
+{
+  if (! primary_func_tmpl_inst
+      || TREE_CODE (primary_func_tmpl_inst) != FUNCTION_DECL
+      || ! primary_template_instantiation_p (primary_func_tmpl_inst))
+    return NULL;
+
+  return DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (primary_func_tmpl_inst));
+}
+
+/* Return true iff the function parameter PARAM_DECL was expanded
+   from the function parameter pack PACK.  */
+
+bool
+function_parameter_expanded_from_pack_p (tree param_decl, tree pack)
+{
+    if (DECL_ARTIFICIAL (param_decl)
+       || !function_parameter_pack_p (pack))
+      return false;
+
+    gcc_assert (DECL_NAME (param_decl) && DECL_NAME (pack));
+
+    /* The parameter pack and its pack arguments have the same
+       DECL_PARM_INDEX.  */
+    return DECL_PARM_INDEX (pack) == DECL_PARM_INDEX (param_decl);
+}
+
 /* Determine whether ARGS describes a variadic template args list,
    i.e., one that is terminated by a template argument pack.  */
+
 static bool 
 template_args_variadic_p (tree args)
 {
@@ -2656,19 +2709,96 @@ template_args_variadic_p (tree args)
 
 /* Generate a new name for the parameter pack name NAME (an
    IDENTIFIER_NODE) that incorporates its */
+
 static tree
 make_ith_pack_parameter_name (tree name, int i)
 {
   /* Munge the name to include the parameter index.  */
-  char numbuf[128];
+#define NUMBUF_LEN 128
+  char numbuf[NUMBUF_LEN];
   char* newname;
-  
-  sprintf(numbuf, "%i", i);
-  newname = (char*)alloca (IDENTIFIER_LENGTH (name) + strlen(numbuf) + 2);
-  sprintf(newname, "%s#%i", IDENTIFIER_POINTER (name), i);
+  int newname_len;
+
+  snprintf (numbuf, NUMBUF_LEN, "%i", i);
+  newname_len = IDENTIFIER_LENGTH (name)
+               + strlen (numbuf) + 2;
+  newname = (char*)alloca (newname_len);
+  snprintf (newname, newname_len,
+           "%s#%i", IDENTIFIER_POINTER (name), i);
   return get_identifier (newname);
 }
 
+/* Return true if T is a primary function
+   or class template instantiation.  */
+
+static bool
+primary_template_instantiation_p (const_tree t)
+{
+  if (!t)
+    return false;
+
+  if (TREE_CODE (t) == FUNCTION_DECL)
+    return DECL_LANG_SPECIFIC (t)
+          && DECL_TEMPLATE_INSTANTIATION (t)
+          && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t));
+  else if (CLASS_TYPE_P (t))
+    return CLASSTYPE_TEMPLATE_INSTANTIATION (t)
+          && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t));
+  return false;
+}
+
+/* Return true if PARM is a template template parameter.  */
+
+bool
+template_template_parameter_p (const_tree parm)
+{
+  return DECL_TEMPLATE_TEMPLATE_PARM_P (parm);
+}
+
+/* Return the template parameters of T if T is a
+   primary template instantiation, NULL otherwise.  */
+
+tree
+get_primary_template_innermost_parameters (const_tree t)
+{
+  tree parms = NULL, template_info = NULL;
+
+  if ((template_info = get_template_info (t))
+      && primary_template_instantiation_p (t))
+    parms = INNERMOST_TEMPLATE_PARMS
+       (DECL_TEMPLATE_PARMS (TI_TEMPLATE (template_info)));
+
+  return parms;
+}
+
+/* Returns the template arguments of T if T is a template instantiation,
+   NULL otherwise.  */
+
+tree
+get_template_innermost_arguments (const_tree t)
+{
+  tree args = NULL, template_info = NULL;
+
+  if ((template_info = get_template_info (t))
+      && TI_ARGS (template_info))
+    args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (template_info));
+
+  return args;
+}
+
+/* Return the argument pack elements of T if T is a template argument pack,
+   NULL otherwise.  */
+
+tree
+get_template_argument_pack_elems (const_tree t)
+{
+  if (TREE_CODE (t) != TYPE_ARGUMENT_PACK
+      && TREE_CODE (t) != NONTYPE_ARGUMENT_PACK)
+    return NULL;
+
+  return ARGUMENT_PACK_ARGS (t);
+}
+
 /* Structure used to track the progress of find_parameter_packs_r.  */
 struct find_parameter_pack_data 
 {
@@ -2888,7 +3018,7 @@ make_pack_expansion (tree arg)
       pointer_set_destroy (ppd.visited);
 
       /* Create the pack expansion type for the base type.  */
-      purpose = make_node (TYPE_PACK_EXPANSION);
+      purpose = cxx_make_type (TYPE_PACK_EXPANSION);
       SET_PACK_EXPANSION_PATTERN (purpose, TREE_PURPOSE (arg));
       PACK_EXPANSION_PARAMETER_PACKS (purpose) = parameter_packs;
 
@@ -2903,7 +3033,9 @@ make_pack_expansion (tree arg)
     for_types = true;
 
   /* Build the PACK_EXPANSION_* node.  */
-  result = make_node (for_types ? TYPE_PACK_EXPANSION : EXPR_PACK_EXPANSION);
+  result = for_types
+     ? cxx_make_type (TYPE_PACK_EXPANSION)
+     : make_node (EXPR_PACK_EXPANSION);
   SET_PACK_EXPANSION_PATTERN (result, arg);
   if (TREE_CODE (result) == EXPR_PACK_EXPANSION)
     {
@@ -3413,7 +3545,7 @@ current_template_args (void)
                           tree vec = make_tree_vec (1);
                           TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
                           
-                          t = make_node (TYPE_ARGUMENT_PACK);
+                          t = cxx_make_type (TYPE_ARGUMENT_PACK);
                           SET_ARGUMENT_PACK_ARGS (t, vec);
                         }
                     }
@@ -5450,7 +5582,7 @@ coerce_template_parameter_pack (tree parms,
 
   if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
       || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
-    argument_pack = make_node (TYPE_ARGUMENT_PACK);
+    argument_pack = cxx_make_type (TYPE_ARGUMENT_PACK);
   else
     {
       argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
@@ -6105,6 +6237,7 @@ lookup_template_class (tree d1,
 
       if (!is_partial_instantiation
          && !PRIMARY_TEMPLATE_P (gen_tmpl)
+         && !LAMBDA_TYPE_P (TREE_TYPE (gen_tmpl))
          && TREE_CODE (CP_DECL_CONTEXT (gen_tmpl)) == NAMESPACE_DECL)
        {
          found = xref_tag_from_type (TREE_TYPE (gen_tmpl),
@@ -6135,7 +6268,7 @@ lookup_template_class (tree d1,
                  the values for the enumeration constants may involve
                  template parameters.  And, no one should be interested
                  in the enumeration constants for such a type.  */
-              t = make_node (ENUMERAL_TYPE);
+              t = cxx_make_type (ENUMERAL_TYPE);
               SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
             }
        }
@@ -7690,7 +7823,7 @@ make_fnparm_pack (tree spec_parm)
   tree parmvec;
   tree parmtypevec;
   tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
-  tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
+  tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
   int i, len = list_length (spec_parm);
 
   /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters.  */
@@ -7957,6 +8090,36 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   return result;
 }
 
+/* Given PARM_DECL PARM, find the corresponding PARM_DECL in the template
+   TMPL.  We do this using DECL_PARM_INDEX, which should work even with
+   parameter packs; all parms generated from a function parameter pack will
+   have the same DECL_PARM_INDEX.  */
+
+tree
+get_pattern_parm (tree parm, tree tmpl)
+{
+  tree pattern = DECL_TEMPLATE_RESULT (tmpl);
+  tree patparm;
+
+  if (DECL_ARTIFICIAL (parm))
+    {
+      for (patparm = DECL_ARGUMENTS (pattern);
+          patparm; patparm = TREE_CHAIN (patparm))
+       if (DECL_ARTIFICIAL (patparm)
+           && DECL_NAME (parm) == DECL_NAME (patparm))
+         break;
+    }
+  else
+    {
+      patparm = FUNCTION_FIRST_USER_PARM (DECL_TEMPLATE_RESULT (tmpl));
+      patparm = chain_index (DECL_PARM_INDEX (parm)-1, patparm);
+      gcc_assert (DECL_PARM_INDEX (patparm)
+                 == DECL_PARM_INDEX (parm));
+    }
+
+  return patparm;
+}
+
 /* Substitute ARGS into the vector or list of template arguments T.  */
 
 static tree
@@ -7991,7 +8154,9 @@ tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       else if (ARGUMENT_PACK_P (orig_arg))
         {
           /* Substitute into each of the arguments.  */
-          new_arg = make_node (TREE_CODE (orig_arg));
+          new_arg = TYPE_P (orig_arg)
+            ? cxx_make_type (TREE_CODE (orig_arg))
+            : make_node (TREE_CODE (orig_arg));
           
           SET_ARGUMENT_PACK_ARGS (
             new_arg,
@@ -8717,6 +8882,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
             if (DECL_TEMPLATE_PARM_P (t))
               SET_DECL_TEMPLATE_PARM_P (r);
 
+           /* An argument of a function parameter pack is not a parameter
+              pack.  */
+           FUNCTION_PARAMETER_PACK_P (r) = false;
+
             if (expanded_types)
               /* We're on the Ith parameter of the function parameter
                  pack.  */
@@ -9003,6 +9172,22 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            DECL_TEMPLATE_INFO (r) = tree_cons (tmpl, argvec, NULL_TREE);
            SET_DECL_IMPLICIT_INSTANTIATION (r);
          }
+       else if (cp_unevaluated_operand)
+         {
+           /* We're substituting this var in a decltype outside of its
+              scope, such as for a lambda return type.  Don't add it to
+              local_specializations, do perform auto deduction.  */
+           tree auto_node = type_uses_auto (type);
+           tree init
+             = tsubst_expr (DECL_INITIAL (t), args, complain, in_decl,
+                            /*constant_expression_p=*/false);
+
+           if (auto_node && init && describable_type (init))
+             {
+               type = do_auto_deduction (type, init, auto_node);
+               TREE_TYPE (r) = type;
+             }
+         }
        else
          register_local_specialization (r, t);
 
@@ -9994,9 +10179,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        --cp_unevaluated_operand;
        --c_inhibit_evaluation_warnings;
 
-       type =
-          finish_decltype_type (type,
-                                DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
+       if (DECLTYPE_FOR_LAMBDA_CAPTURE (t))
+         type = lambda_capture_field_type (type);
+       else if (DECLTYPE_FOR_LAMBDA_RETURN (t))
+         type = lambda_return_type (type);
+       else
+         type = finish_decltype_type
+           (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
        return cp_build_qualified_type_real (type,
                                             cp_type_quals (t)
                                             | cp_type_quals (type),
@@ -10006,7 +10195,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case TYPE_ARGUMENT_PACK:
     case NONTYPE_ARGUMENT_PACK:
       {
-        tree r = make_node (TREE_CODE (t));
+        tree r = TYPE_P (t)
+          ? cxx_make_type (TREE_CODE (t))
+          : make_node (TREE_CODE (t));
         tree packed_out = 
           tsubst_template_args (ARGUMENT_PACK_ARGS (t), 
                                 args,
@@ -10742,7 +10933,7 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
   if (purpose)
     purpose = RECUR (purpose);
   value = TREE_VALUE (t);
-  if (value)
+  if (value && TREE_CODE (value) != LABEL_DECL)
     value = RECUR (value);
   chain = TREE_CHAIN (t);
   if (chain && chain != void_type_node)
@@ -11134,7 +11325,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree 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));
+        tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl),
+        tsubst_copy_asm_operands (ASM_LABELS (t), args, complain, in_decl));
       {
        tree asm_expr = tmp;
        if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
@@ -12199,6 +12391,39 @@ tsubst_copy_and_build (tree t,
        }
       return t;
 
+    case LAMBDA_EXPR:
+      {
+       tree r = build_lambda_expr ();
+
+       tree type = tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
+       TREE_TYPE (r) = type;
+       CLASSTYPE_LAMBDA_EXPR (type) = r;
+
+       LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)
+         = LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t);
+       LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
+       LAMBDA_EXPR_DISCRIMINATOR (r)
+         = (LAMBDA_EXPR_DISCRIMINATOR (t));
+       LAMBDA_EXPR_CAPTURE_LIST (r)
+         = RECUR (LAMBDA_EXPR_CAPTURE_LIST (t));
+       LAMBDA_EXPR_THIS_CAPTURE (r)
+         = RECUR (LAMBDA_EXPR_THIS_CAPTURE (t));
+       LAMBDA_EXPR_EXTRA_SCOPE (r)
+         = RECUR (LAMBDA_EXPR_EXTRA_SCOPE (t));
+
+       /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set.  */
+       determine_visibility (TYPE_NAME (type));
+       /* Now that we know visibility, instantiate the type so we have a
+          declaration of the op() for later calls to lambda_function.  */
+       complete_type (type);
+
+       type = tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
+       if (type)
+         apply_lambda_return_type (r, type);
+
+       return build_lambda_object (r);
+      }
+
     default:
       /* Handle Objective-C++ constructs, if appropriate.  */
       {
@@ -12953,7 +13178,7 @@ type_unification_real (tree tparms,
                   TREE_CONSTANT (arg) = 1;
                 }
               else
-                arg = make_node (TYPE_ARGUMENT_PACK);
+                arg = cxx_make_type (TYPE_ARGUMENT_PACK);
 
               SET_ARGUMENT_PACK_ARGS (arg, make_tree_vec (0));
 
@@ -13530,7 +13755,7 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
               TREE_CONSTANT (result) = 1;
             }
           else
-            result = make_node (TYPE_ARGUMENT_PACK);
+            result = cxx_make_type (TYPE_ARGUMENT_PACK);
 
           SET_ARGUMENT_PACK_ARGS (result, new_args);
 
@@ -13650,6 +13875,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
     {
       tree elt, elttype;
       unsigned i;
+      tree orig_parm = parm;
+
+      /* Replace T with std::initializer_list<T> for deduction.  */
+      if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+         && flag_deduce_init_list)
+       parm = listify (parm);
 
       if (!is_std_init_list (parm))
        /* We can only deduce from an initializer list argument if the
@@ -13675,6 +13906,16 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
          if (unify (tparms, targs, elttype, elt, elt_strict))
            return 1;
        }
+
+      /* If the std::initializer_list<T> deduction worked, replace the
+        deduced A with std::initializer_list<A>.  */
+      if (orig_parm != parm)
+       {
+         idx = TEMPLATE_TYPE_IDX (orig_parm);
+         targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
+         targ = listify (targ);
+         TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = targ;
+       }
       return 0;
     }
 
@@ -15783,10 +16024,11 @@ instantiate_decl (tree d, int defer_ok,
       SET_DECL_IMPLICIT_INSTANTIATION (d);
     }
 
-  if (!defer_ok)
+  /* Recheck the substitutions to obtain any warning messages
+     about ignoring cv qualifiers.  Don't do this for artificial decls,
+     as it breaks the context-sensitive substitution for lambda op(). */
+  if (!defer_ok && !DECL_ARTIFICIAL (d))
     {
-      /* Recheck the substitutions to obtain any warning messages
-        about ignoring cv qualifiers.  */
       tree gen = DECL_TEMPLATE_RESULT (gen_tmpl);
       tree type = TREE_TYPE (gen);
 
@@ -17369,26 +17611,33 @@ make_auto (void)
   return au;
 }
 
-/* Replace auto in TYPE with std::initializer_list<auto>.  */
+/* Given type ARG, return std::initializer_list<ARG>.  */
 
 static tree
-listify_autos (tree type, tree auto_node)
+listify (tree arg)
 {
   tree std_init_list = namespace_binding
     (get_identifier ("initializer_list"), std_node);
   tree argvec;
-  tree init_auto;
   if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
     {    
-      error ("deducing auto from brace-enclosed initializer list requires "
+      error ("deducing from brace-enclosed initializer list requires "
             "#include <initializer_list>");
       return error_mark_node;
     }
   argvec = make_tree_vec (1);
-  TREE_VEC_ELT (argvec, 0) = auto_node;
-  init_auto = lookup_template_class (std_init_list, argvec, NULL_TREE,
-                                    NULL_TREE, 0, tf_warning_or_error);
+  TREE_VEC_ELT (argvec, 0) = arg;
+  return lookup_template_class (std_init_list, argvec, NULL_TREE,
+                               NULL_TREE, 0, tf_warning_or_error);
+}
+
+/* Replace auto in TYPE with std::initializer_list<auto>.  */
 
+static tree
+listify_autos (tree type, tree auto_node)
+{
+  tree init_auto = listify (auto_node);
+  tree argvec = make_tree_vec (1);
   TREE_VEC_ELT (argvec, 0) = init_auto;
   if (processing_template_decl)
     argvec = add_to_template_args (current_template_args (), argvec);