summaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c203
1 files changed, 123 insertions, 80 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 09d077ade06..7a331479d8b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -158,7 +158,7 @@ static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void regenerate_decl_from_template (tree, tree);
-static tree most_specialized_class (tree, tree);
+static tree most_specialized_class (tree, tree, tsubst_flags_t);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
@@ -1566,31 +1566,43 @@ iterative_hash_template_arg (tree arg, hashval_t val)
gcc_assert (seen_error ());
return val;
+ case CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ case NEW_EXPR:
+ val = iterative_hash_template_arg (TREE_TYPE (arg), val);
+ /* Now hash operands as usual. */
+ break;
+
default:
- switch (tclass)
- {
- case tcc_type:
- if (TYPE_CANONICAL (arg))
- return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
- val);
- else if (TREE_CODE (arg) == DECLTYPE_TYPE)
- return iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
- /* Otherwise just compare the types during lookup. */
- return val;
+ break;
+ }
- case tcc_declaration:
- case tcc_constant:
- return iterative_hash_expr (arg, val);
+ switch (tclass)
+ {
+ case tcc_type:
+ if (TYPE_CANONICAL (arg))
+ return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
+ val);
+ else if (TREE_CODE (arg) == DECLTYPE_TYPE)
+ return iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
+ /* Otherwise just compare the types during lookup. */
+ return val;
- default:
- gcc_assert (IS_EXPR_CODE_CLASS (tclass));
- {
- unsigned n = TREE_OPERAND_LENGTH (arg);
- for (i = 0; i < n; ++i)
- val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
- return val;
- }
- }
+ case tcc_declaration:
+ case tcc_constant:
+ return iterative_hash_expr (arg, val);
+
+ default:
+ gcc_assert (IS_EXPR_CODE_CLASS (tclass));
+ {
+ unsigned n = TREE_OPERAND_LENGTH (arg);
+ for (i = 0; i < n; ++i)
+ val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
+ return val;
+ }
}
gcc_unreachable ();
return 0;
@@ -2553,7 +2565,7 @@ check_explicit_specialization (tree declarator,
definition, not in the original declaration. */
DECL_ARGUMENTS (result) = DECL_ARGUMENTS (decl);
for (parm = DECL_ARGUMENTS (result); parm;
- parm = TREE_CHAIN (parm))
+ parm = DECL_CHAIN (parm))
DECL_CONTEXT (parm) = result;
}
return register_specialization (tmpl, gen_tmpl, targs,
@@ -3831,6 +3843,7 @@ process_partial_specialization (tree decl)
tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
tree inner_parms;
+ tree inst;
int nargs = TREE_VEC_LENGTH (inner_args);
int ntparms;
int i;
@@ -4045,6 +4058,22 @@ process_partial_specialization (tree decl)
= tree_cons (specargs, inner_parms,
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+
+ for (inst = DECL_TEMPLATE_INSTANTIATIONS (maintmpl); inst;
+ inst = TREE_CHAIN (inst))
+ {
+ tree inst_type = TREE_VALUE (inst);
+ if (COMPLETE_TYPE_P (inst_type)
+ && CLASSTYPE_IMPLICIT_INSTANTIATION (inst_type))
+ {
+ tree spec = most_specialized_class (inst_type, maintmpl, tf_none);
+ if (spec && TREE_TYPE (spec) == type)
+ permerror (input_location,
+ "partial specialization of %qT after instantiation "
+ "of %qT", type, inst_type);
+ }
+ }
+
return decl;
}
@@ -4417,7 +4446,7 @@ push_template_decl_real (tree decl, bool is_friend)
TREE_VALUE (argtype) = error_mark_node;
}
- arg = TREE_CHAIN (arg);
+ arg = DECL_CHAIN (arg);
argtype = TREE_CHAIN (argtype);
}
@@ -7749,7 +7778,7 @@ instantiate_class_template (tree type)
/* Determine what specialization of the original template to
instantiate. */
- t = most_specialized_class (type, templ);
+ t = most_specialized_class (type, templ, tf_warning_or_error);
if (t == error_mark_node)
{
TYPE_BEING_DEFINED (type) = 1;
@@ -7803,7 +7832,8 @@ instantiate_class_template (tree type)
/* Set the input location to the most specialized template definition.
This is needed if tsubsting causes an error. */
typedecl = TYPE_MAIN_DECL (pattern);
- input_location = DECL_SOURCE_LOCATION (typedecl);
+ input_location = DECL_SOURCE_LOCATION (TYPE_NAME (type)) =
+ DECL_SOURCE_LOCATION (typedecl);
TYPE_HAS_USER_CONSTRUCTOR (type) = TYPE_HAS_USER_CONSTRUCTOR (pattern);
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
@@ -8196,7 +8226,7 @@ instantiate_class_template (tree type)
any member functions. We don't do this earlier because the
default arguments may reference members of the class. */
if (!PRIMARY_TEMPLATE_P (templ))
- for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
+ for (t = TYPE_METHODS (type); t; t = DECL_CHAIN (t))
if (TREE_CODE (t) == FUNCTION_DECL
/* Implicitly generated member functions will not have template
information; they are not instantiations, but instead are
@@ -8261,7 +8291,7 @@ make_fnparm_pack (tree spec_parm)
/* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
parmvec = make_tree_vec (len);
parmtypevec = make_tree_vec (len);
- for (i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
+ for (i = 0; i < len; i++, spec_parm = DECL_CHAIN (spec_parm))
{
TREE_VEC_ELT (parmvec, i) = spec_parm;
TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
@@ -8541,7 +8571,7 @@ get_pattern_parm (tree parm, tree tmpl)
if (DECL_ARTIFICIAL (parm))
{
for (patparm = DECL_ARGUMENTS (pattern);
- patparm; patparm = TREE_CHAIN (patparm))
+ patparm; patparm = DECL_CHAIN (patparm))
if (DECL_ARTIFICIAL (patparm)
&& DECL_NAME (parm) == DECL_NAME (patparm))
break;
@@ -8936,7 +8966,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
RETURN (error_mark_node);
r = copy_decl (t);
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
TREE_TYPE (r) = new_type;
DECL_TEMPLATE_RESULT (r)
= build_decl (DECL_SOURCE_LOCATION (decl),
@@ -8986,7 +9016,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
than the old one. */
r = copy_decl (t);
gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
@@ -9196,7 +9226,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
assigned to the instantiation. */
DECL_INTERFACE_KNOWN (r) = !TREE_PUBLIC (r);
DECL_DEFER_OUTPUT (r) = 0;
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
DECL_PENDING_INLINE_INFO (r) = 0;
DECL_PENDING_INLINE_P (r) = 0;
DECL_SAVED_TREE (r) = NULL_TREE;
@@ -9395,12 +9425,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Build a proper chain of parameters when substituting
into a function parameter pack. */
if (prev_r)
- TREE_CHAIN (prev_r) = r;
+ DECL_CHAIN (prev_r) = r;
}
- if (TREE_CHAIN (t))
- TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args,
- complain, TREE_CHAIN (t));
+ if (DECL_CHAIN (t))
+ DECL_CHAIN (r) = tsubst (DECL_CHAIN (t), args,
+ complain, DECL_CHAIN (t));
/* FIRST_R contains the start of the chain we've built. */
r = first_r;
@@ -9425,7 +9455,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/*integral_constant_expression_p=*/true);
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type))
error ("instantiation of %q+D as type %qT", r, type);
@@ -9452,7 +9482,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
else
{
r = copy_node (t);
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
}
break;
@@ -9652,7 +9682,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
else
register_local_specialization (r, t);
- TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
/*flags=*/0,
@@ -9958,6 +9988,7 @@ tsubst_exception_specification (tree fntype,
tree
tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
+ enum tree_code code;
tree type, r;
if (t == NULL_TREE || t == error_mark_node
@@ -9974,7 +10005,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (args == NULL_TREE)
return t;
- if (TREE_CODE (t) == IDENTIFIER_NODE)
+ code = TREE_CODE (t);
+
+ if (code == IDENTIFIER_NODE)
type = IDENTIFIER_TYPE_VALUE (t);
else
type = TREE_TYPE (t);
@@ -10017,16 +10050,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
if (type
- && TREE_CODE (t) != TYPENAME_TYPE
- && TREE_CODE (t) != TEMPLATE_TYPE_PARM
- && TREE_CODE (t) != IDENTIFIER_NODE
- && TREE_CODE (t) != FUNCTION_TYPE
- && TREE_CODE (t) != METHOD_TYPE)
+ && code != TYPENAME_TYPE
+ && code != TEMPLATE_TYPE_PARM
+ && code != IDENTIFIER_NODE
+ && code != FUNCTION_TYPE
+ && code != METHOD_TYPE)
type = tsubst (type, args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
- switch (TREE_CODE (t))
+ switch (code)
{
case RECORD_TYPE:
case UNION_TYPE:
@@ -10156,7 +10189,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}; */
return t;
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ if (code == TEMPLATE_TYPE_PARM)
{
int quals;
gcc_assert (TYPE_P (arg));
@@ -10166,7 +10199,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return cp_build_qualified_type_real
(arg, quals, complain | tf_ignore_bad_quals);
}
- else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ else if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
{
/* We are processing a type constructed from a
template template parameter. */
@@ -10205,7 +10238,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* If we get here, we must have been looking at a parm for a
more deeply nested template. Make a new version of this
template parameter, but with a lower level. */
- switch (TREE_CODE (t))
+ switch (code)
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
@@ -10215,7 +10248,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
r = cp_build_qualified_type_real
(r, cp_type_quals (t),
- complain | (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ complain | (code == TEMPLATE_TYPE_PARM
? tf_ignore_bad_quals : 0));
}
else
@@ -10243,7 +10276,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else
TYPE_CANONICAL (r) = canonical_type_parameter (r);
- if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
{
tree argvec = tsubst (TYPE_TI_ARGS (t), args,
complain, in_decl);
@@ -10314,14 +10347,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case POINTER_TYPE:
case REFERENCE_TYPE:
{
- enum tree_code code;
-
if (type == TREE_TYPE (t) && TREE_CODE (type) != METHOD_TYPE)
return t;
- code = TREE_CODE (t);
-
-
/* [temp.deduct]
Type deduction may fail for any of the following
@@ -10506,7 +10534,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return error_mark_node;
return fold_build2_loc (input_location,
- TREE_CODE (t), TREE_TYPE (t), e1, e2);
+ code, TREE_TYPE (t), e1, e2);
}
case NEGATE_EXPR:
@@ -10516,7 +10544,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (e == error_mark_node)
return error_mark_node;
- return fold_build1_loc (input_location, TREE_CODE (t), TREE_TYPE (t), e);
+ return fold_build1_loc (input_location, code, TREE_TYPE (t), e);
}
case TYPENAME_TYPE:
@@ -10672,9 +10700,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
- tree r = TYPE_P (t)
- ? cxx_make_type (TREE_CODE (t))
- : make_node (TREE_CODE (t));
+ tree r = TYPE_P (t) ? cxx_make_type (code) : make_node (code);
tree packed_out =
tsubst_template_args (ARGUMENT_PACK_ARGS (t),
args,
@@ -10684,7 +10710,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* For template nontype argument packs, also substitute into
the type. */
- if (TREE_CODE (t) == NONTYPE_ARGUMENT_PACK)
+ if (code == NONTYPE_ARGUMENT_PACK)
TREE_TYPE (r) = tsubst (TREE_TYPE (t), args, complain, in_decl);
return r;
@@ -10692,8 +10718,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
break;
default:
- sorry ("use of %qs in template",
- tree_code_name [(int) TREE_CODE (t)]);
+ sorry ("use of %qs in template", tree_code_name [(int) code]);
return error_mark_node;
}
}
@@ -10737,6 +10762,8 @@ tsubst_baselink (tree baselink, tree object_type,
if (IDENTIFIER_TYPENAME_P (name))
name = mangle_conv_op_name_for_type (optype);
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
+ if (!baselink)
+ return error_mark_node;
/* If lookup found a single function, mark it as used at this
point. (If it lookup found multiple functions the one selected
@@ -11312,8 +11339,13 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_unreachable ();
case OFFSET_REF:
- mark_used (TREE_OPERAND (t, 1));
- return t;
+ r = build2
+ (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+ PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
+ mark_used (TREE_OPERAND (r, 1));
+ return r;
case EXPR_PACK_EXPANSION:
error ("invalid use of pack expansion expression");
@@ -12500,15 +12532,24 @@ tsubst_copy_and_build (tree t,
ret = build_offset_ref_call_from_tree (function, &call_args);
else if (TREE_CODE (function) == COMPONENT_REF)
{
- if (!BASELINK_P (TREE_OPERAND (function, 1)))
+ tree instance = TREE_OPERAND (function, 0);
+ tree fn = TREE_OPERAND (function, 1);
+
+ if (processing_template_decl
+ && (type_dependent_expression_p (instance)
+ || (!BASELINK_P (fn)
+ && TREE_CODE (fn) != FIELD_DECL)
+ || type_dependent_expression_p (fn)
+ || any_type_dependent_arguments_p (call_args)))
+ ret = build_nt_call_vec (function, call_args);
+ else if (!BASELINK_P (fn))
ret = finish_call_expr (function, &call_args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
complain);
else
ret = (build_new_method_call
- (TREE_OPERAND (function, 0),
- TREE_OPERAND (function, 1),
+ (instance, fn,
&call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
/*fn_p=*/NULL,
@@ -13121,7 +13162,7 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
instantiate all the alternate entry points as well. We do this
by cloning the instantiation of the main entry point, not by
instantiating the template clones. */
- if (TREE_CHAIN (gen_tmpl) && DECL_CLONED_FUNCTION_P (TREE_CHAIN (gen_tmpl)))
+ if (DECL_CHAIN (gen_tmpl) && DECL_CLONED_FUNCTION_P (DECL_CHAIN (gen_tmpl)))
clone_function_decl (fndecl, /*update_method_vec_p=*/0);
return fndecl;
@@ -15972,7 +16013,7 @@ most_general_template (tree decl)
returned. */
static tree
-most_specialized_class (tree type, tree tmpl)
+most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
{
tree list = NULL_TREE;
tree t;
@@ -16092,6 +16133,8 @@ most_specialized_class (tree type, tree tmpl)
{
const char *str;
char *spaces = NULL;
+ if (!(complain & tf_error))
+ return error_mark_node;
error ("ambiguous class template instantiation for %q#T", type);
str = TREE_CHAIN (list) ? _("candidates are:") : _("candidate is:");
for (t = list; t; t = TREE_CHAIN (t))
@@ -16390,12 +16433,12 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
interpretation is that it should be an explicit instantiation. */
if (! static_p)
- for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
+ for (tmp = TYPE_METHODS (t); tmp; tmp = DECL_CHAIN (tmp))
if (TREE_CODE (tmp) == FUNCTION_DECL
&& DECL_TEMPLATE_INSTANTIATION (tmp))
instantiate_class_member (tmp, extern_p);
- for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
+ for (tmp = TYPE_FIELDS (t); tmp; tmp = DECL_CHAIN (tmp))
if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp))
instantiate_class_member (tmp, extern_p);
@@ -16483,8 +16526,8 @@ regenerate_decl_from_template (tree decl, tree tmpl)
DECL_ATTRIBUTES (decl_parm) = attributes;
cplus_decl_attributes (&decl_parm, attributes, /*flags=*/0);
}
- decl_parm = TREE_CHAIN (decl_parm);
- pattern_parm = TREE_CHAIN (pattern_parm);
+ decl_parm = DECL_CHAIN (decl_parm);
+ pattern_parm = DECL_CHAIN (pattern_parm);
}
/* Merge any parameters that match with the function parameter
pack. */
@@ -16516,7 +16559,7 @@ regenerate_decl_from_template (tree decl, tree tmpl)
DECL_ATTRIBUTES (decl_parm) = attributes;
cplus_decl_attributes (&decl_parm, attributes, /*flags=*/0);
}
- decl_parm = TREE_CHAIN (decl_parm);
+ decl_parm = DECL_CHAIN (decl_parm);
}
}
/* Merge additional specifiers from the CODE_PATTERN. */
@@ -16926,8 +16969,8 @@ instantiate_decl (tree d, int defer_ok,
while (tmpl_parm && !FUNCTION_PARAMETER_PACK_P (tmpl_parm))
{
register_local_specialization (spec_parm, tmpl_parm);
- tmpl_parm = TREE_CHAIN (tmpl_parm);
- spec_parm = TREE_CHAIN (spec_parm);
+ tmpl_parm = DECL_CHAIN (tmpl_parm);
+ spec_parm = DECL_CHAIN (spec_parm);
}
if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm))
{
@@ -16935,7 +16978,7 @@ instantiate_decl (tree d, int defer_ok,
TMPL_PARM, then move on. */
tree argpack = make_fnparm_pack (spec_parm);
register_local_specialization (argpack, tmpl_parm);
- tmpl_parm = TREE_CHAIN (tmpl_parm);
+ tmpl_parm = DECL_CHAIN (tmpl_parm);
spec_parm = NULL_TREE;
}
gcc_assert (!spec_parm);