diff options
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ee38254bd8c..636909db5c0 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -943,7 +943,7 @@ maybe_process_partial_specialization (tree type) /* Someday C++0x may allow for enum template specialization. */ if (cxx_dialect > cxx98 && TREE_CODE (type) == ENUMERAL_TYPE && CLASS_TYPE_P (context) && CLASSTYPE_USE_TEMPLATE (context)) - pedwarn (input_location, OPT_pedantic, "template specialization " + pedwarn (input_location, OPT_Wpedantic, "template specialization " "of %qD not allowed by ISO C++", type); else { @@ -1839,6 +1839,7 @@ determine_specialization (tree template_id, { tree decl_arg_types; tree fn_arg_types; + tree insttype; /* In case of explicit specialization, we need to check if the number of template headers appearing in the specialization @@ -1900,15 +1901,6 @@ determine_specialization (tree template_id, fn_arg_types = skip_artificial_parms_for (fn, fn_arg_types); - /* Check that the number of function parameters matches. - For example, - template <class T> void f(int i = 0); - template <> void f<int>(); - The specialization f<int> is invalid but is not caught - by get_bindings below. */ - if (list_length (fn_arg_types) != list_length (decl_arg_types)) - continue; - /* Function templates cannot be specializations; there are no partial specializations of functions. Therefore, if the type of DECL does not match FN, there is no @@ -1929,6 +1921,15 @@ determine_specialization (tree template_id, specialize TMPL will produce DECL. */ continue; + /* Make sure that the deduced arguments actually work. */ + insttype = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE); + if (insttype == error_mark_node) + continue; + fn_arg_types + = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (insttype)); + if (!compparms (fn_arg_types, decl_arg_types)) + continue; + /* Save this template, and the arguments deduced. */ templates = tree_cons (targs, fn, templates); } @@ -4376,6 +4377,18 @@ process_partial_specialization (tree decl) (maintmpl))))) error ("partial specialization %qT does not specialize any template arguments", type); + /* A partial specialization that replaces multiple parameters of the + primary template with a pack expansion is less specialized for those + parameters. */ + if (nargs < DECL_NTPARMS (maintmpl)) + { + error ("partial specialization is not more specialized than the " + "primary template because it replaces multiple parameters " + "with a pack expansion"); + inform (DECL_SOURCE_LOCATION (maintmpl), "primary template here"); + return decl; + } + /* [temp.class.spec] A partially specialized non-type argument expression shall not @@ -5679,7 +5692,11 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) value_dependent_expression_p. */ if (TYPE_PTROBV_P (type) && TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE) - expr = decay_conversion (expr); + { + expr = decay_conversion (expr, complain); + if (expr == error_mark_node) + return error_mark_node; + } /* If we are in a template, EXPR may be non-dependent, but still have a syntactic, rather than semantic, form. For example, EXPR @@ -5887,7 +5904,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) } } - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); if (expr == error_mark_node) return error_mark_node; @@ -5972,7 +5989,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) context information to decay the pointer. */ if (!type_unknown_p (expr_type)) { - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); if (expr == error_mark_node) return error_mark_node; } @@ -6416,7 +6433,7 @@ convert_template_argument (tree parm, if (cxx_dialect >= cxx0x) /* OK under DR 1004. */; else if (complain & tf_warning_or_error) - pedwarn (input_location, OPT_pedantic, "injected-class-name %qD" + pedwarn (input_location, OPT_Wpedantic, "injected-class-name %qD" " used as template template argument", TYPE_NAME (arg)); else if (flag_pedantic_errors) t = arg; @@ -6428,6 +6445,7 @@ convert_template_argument (tree parm, is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL) + || (requires_tmpl_type && TREE_CODE (arg) == TYPE_ARGUMENT_PACK) || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE); @@ -6499,7 +6517,9 @@ convert_template_argument (tree parm, { if (requires_tmpl_type) { - if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE) + if (template_parameter_pack_p (parm) && ARGUMENT_PACK_P (orig_arg)) + val = orig_arg; + else if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE) /* The number of argument required is not known yet. Just accept it for now. */ val = TREE_TYPE (arg); @@ -6697,7 +6717,12 @@ coerce_template_parameter_pack (tree parms, TREE_VEC_ELT (packed_types, arg_idx - parm_idx); } - if (arg != error_mark_node) + if (arg == error_mark_node) + { + if (complain & tf_error) + error ("template argument %d is invalid", arg_idx + 1); + } + else arg = convert_template_argument (actual_parm, arg, new_args, complain, parm_idx, in_decl); @@ -6725,6 +6750,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 @@ -6790,6 +6829,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)))))) @@ -6867,7 +6907,7 @@ coerce_template_parms (tree parms, { /* We don't know how many args we have yet, just use the unconverted ones for now. */ - new_inner_args = args; + new_inner_args = inner_args; break; } } @@ -9498,7 +9538,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, } /* Substitute into the PATTERN with the altered arguments. */ - if (TREE_CODE (t) == EXPR_PACK_EXPANSION) + if (!TYPE_P (pattern)) TREE_VEC_ELT (result, i) = tsubst_expr (pattern, args, complain, in_decl, /*integral_constant_expression_p=*/false); @@ -17869,7 +17909,7 @@ do_decl_instantiation (tree decl, tree storage) else if (storage == ridpointers[(int) RID_EXTERN]) { if (!in_system_header && (cxx_dialect == cxx98)) - pedwarn (input_location, OPT_pedantic, + pedwarn (input_location, OPT_Wpedantic, "ISO C++ 1998 forbids the use of %<extern%> on explicit " "instantiations"); extern_p = 1; @@ -17966,12 +18006,12 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain) if (storage == ridpointers[(int) RID_EXTERN]) { if (cxx_dialect == cxx98) - pedwarn (input_location, OPT_pedantic, + pedwarn (input_location, OPT_Wpedantic, "ISO C++ 1998 forbids the use of %<extern%> on " "explicit instantiations"); } else - pedwarn (input_location, OPT_pedantic, + pedwarn (input_location, OPT_Wpedantic, "ISO C++ forbids the use of %qE" " on explicit instantiations", storage); } |