static tree tsubst (tree, tree, tsubst_flags_t, tree);
static tree tsubst_expr (tree, tree, tsubst_flags_t, tree);
static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
-static tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
template constant parameter, like N - 1. Now that we've
tsubst'd, we might have something like 2 - 1. This will
confuse lookup_template_class, so we do constant folding
- here. We have to unset processing_template_decl, to
- fool build_expr_from_tree() into building an actual
- tree. */
+ here. We have to unset processing_template_decl, to fool
+ tsubst_copy_and_build() into building an actual tree. */
/* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
as simple as it's going to get, and trying to reprocess
{
int saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
- arg = build_expr_from_tree (arg);
+ arg = tsubst_copy_and_build (arg,
+ /*args=*/NULL_TREE,
+ tf_error,
+ /*in_decl=*/NULL_TREE);
processing_template_decl = saved_processing_template_decl;
}
}
}
+/* Like tsubst_expr for a BASELINK. OBJECT_TYPE, if non-NULL, is the
+ type of the expression on the left-hand side of the "." or "->"
+ operator. */
+
+static tree
+tsubst_baselink (tree baselink, tree object_type,
+ tree args, tsubst_flags_t complain, tree in_decl)
+{
+ tree name;
+ tree qualifying_scope;
+ tree fns;
+ tree template_args = 0;
+ bool template_id_p = false;
+
+ /* A baselink indicates a function from a base class. The
+ BASELINK_ACCESS_BINFO and BASELINK_BINFO are going to have
+ non-dependent types; otherwise, the lookup could not have
+ succeeded. However, they may indicate bases of the template
+ class, rather than the instantiated class.
+
+ In addition, lookups that were not ambiguous before may be
+ ambiguous now. Therefore, we perform the lookup again. */
+ qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (baselink));
+ fns = BASELINK_FUNCTIONS (baselink);
+ if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
+ {
+ template_id_p = true;
+ template_args = TREE_OPERAND (fns, 1);
+ fns = TREE_OPERAND (fns, 0);
+ template_args = tsubst_copy (template_args, args,
+ complain, in_decl);
+ maybe_fold_nontype_args (template_args);
+ }
+ name = DECL_NAME (get_first_fn (fns));
+ baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
+ if (BASELINK_P (baselink) && template_id_p)
+ BASELINK_FUNCTIONS (baselink)
+ = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (baselink),
+ template_args);
+ if (!object_type)
+ object_type = current_class_type;
+ return adjust_result_of_qualified_name_lookup (baselink,
+ qualifying_scope,
+ object_type);
+}
+
+/* Like tsubst_expr for a SCOPE_REF, given by QUALIFIED_ID. DONE is
+ true if the qualified-id will be a postfix-expression in-and-of
+ itself; false if more of the postfix-expression follows the
+ QUALIFIED_ID. ADDRESS_P is true if the qualified-id is the operand
+ of "&". */
+
+static tree
+tsubst_qualified_id (tree qualified_id, tree args,
+ tsubst_flags_t complain, tree in_decl,
+ bool done, bool address_p)
+{
+ tree expr;
+ tree scope;
+ tree name;
+ bool is_template;
+ tree template_args;
+
+ my_friendly_assert (TREE_CODE (qualified_id) == SCOPE_REF, 20030706);
+
+ /* Look up the qualified name. */
+ scope = TREE_OPERAND (qualified_id, 0);
+ scope = tsubst (scope, args, complain, in_decl);
+
+ /* Figure out what name to look up. */
+ name = TREE_OPERAND (qualified_id, 1);
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ is_template = true;
+ template_args = tsubst_copy_and_build (TREE_OPERAND (name, 1),
+ args, complain, in_decl);
+ name = TREE_OPERAND (name, 0);
+ }
+ else
+ {
+ is_template = false;
+ template_args = NULL_TREE;
+ }
+
+ expr = tsubst_copy (name, args, complain, in_decl);
+ if (!BASELINK_P (name))
+ {
+ expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0);
+ if (DECL_P (expr))
+ check_accessibility_of_qualified_id (expr,
+ /*object_type=*/NULL_TREE,
+ scope);
+ }
+
+ /* Remember that there was a reference to this entity. */
+ if (DECL_P (expr))
+ mark_used (expr);
+
+ if (is_template)
+ lookup_template_function (expr, template_args);
+
+ if (TYPE_P (scope))
+ {
+ expr = (adjust_result_of_qualified_name_lookup
+ (expr, scope, current_class_type));
+ expr = finish_qualified_id_expr (scope, expr, done, address_p);
+ }
+
+ return expr;
+}
+
/* Like tsubst, but deals with expressions. This function just replaces
template parms; to finish processing the resultant expression, use
tsubst_expr. */
return t;
case BASELINK:
- {
- tree name;
- tree qualifying_scope;
- tree fns;
- tree template_args = 0;
- bool template_id_p = false;
-
- /* A baselink indicates a function from a base class. The
- BASELINK_ACCESS_BINFO and BASELINK_BINFO are going to have
- non-dependent types; otherwise, the lookup could not have
- succeeded. However, they may indicate bases of the template
- class, rather than the instantiated class.
-
- In addition, lookups that were not ambiguous before may be
- ambiguous now. Therefore, we perform the lookup again. */
- qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (t));
- fns = BASELINK_FUNCTIONS (t);
- if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
- {
- template_id_p = true;
- template_args = TREE_OPERAND (fns, 1);
- fns = TREE_OPERAND (fns, 0);
- template_args = tsubst_copy (template_args, args,
- complain, in_decl);
- maybe_fold_nontype_args (template_args);
- }
- name = DECL_NAME (get_first_fn (fns));
- t = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
- if (BASELINK_P (t) && template_id_p)
- BASELINK_FUNCTIONS (t)
- = build_nt (TEMPLATE_ID_EXPR,
- BASELINK_FUNCTIONS (t),
- template_args);
- return adjust_result_of_qualified_name_lookup (t,
- qualifying_scope,
- current_class_type);
- }
+ return tsubst_baselink (t, current_class_type, args, complain, in_decl);
case TEMPLATE_DECL:
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
name = build_nt (SCOPE_REF, base, name);
}
+ else if (TREE_CODE (name) == BASELINK)
+ name = tsubst_baselink (name,
+ non_reference (TREE_TYPE (object)),
+ args, complain,
+ in_decl);
else
- name = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ name = tsubst_copy (name, args, complain, in_decl);
return build_nt (COMPONENT_REF, object, name);
}
in_decl),
NULL_TREE);
- case METHOD_CALL_EXPR:
- return build_nt
- (code,
- tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl),
- NULL_TREE);
-
case STMT_EXPR:
/* This processing should really occur in tsubst_expr. However,
tsubst_expr does not recurse into expressions, since it
scope = tsubst_expr (scope, args, complain, in_decl);
do_local_using_decl (lookup_qualified_name (scope,
name,
- /*is_type_p=*/0,
- /*flags=*/0));
+ /*is_type_p=*/0));
}
else
{
/* Like tsubst but deals with expressions and performs semantic
analysis. */
-static tree
+tree
tsubst_copy_and_build (tree t,
tree args,
tsubst_flags_t complain,
tree in_decl)
{
+ tree op1;
+
if (t == NULL_TREE || t == error_mark_node)
return t;
{
tree object;
tree template
- = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
tree targs
- = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ = tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
+ in_decl);
if (TREE_CODE (template) == COMPONENT_REF)
{
}
else
object = NULL_TREE;
- maybe_fold_nontype_args (targs);
template = lookup_template_function (template, targs);
if (object)
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
+ op1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (op1) == SCOPE_REF)
+ op1 = tsubst_qualified_id (TREE_OPERAND (t, 0),
+ args, complain,
+ in_decl,
+ /*done=*/false,
+ /*address_p=*/false);
+ else
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ return build_x_unary_op (TREE_CODE (t), op1);
+
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
if (TREE_TYPE (t))
return tsubst_copy (t, args, complain, in_decl);
else
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
- case TRUTH_NOT_EXPR:
case ADDR_EXPR:
+ op1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (op1) == SCOPE_REF)
+ op1 = tsubst_qualified_id (op1, args, complain, in_decl,
+ /*done=*/true, /*address_p=*/true);
+ else
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ return build_x_unary_op (ADDR_EXPR, op1);
+
+ case TRUTH_NOT_EXPR:
case CONVERT_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
case SCOPE_REF:
- return build_offset_ref
- (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+ return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
+ /*address_p=*/false);
case ARRAY_REF:
- {
- if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
- == NULL_TREE)
- /* new-type-id */
- return build_nt
- (ARRAY_REF, NULL_TREE,
- tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
- in_decl));
-
- return grok_array_decl
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
- in_decl),
+ if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
+ == NULL_TREE)
+ /* new-type-id */
+ return build_nt
+ (ARRAY_REF, NULL_TREE,
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl));
- }
+
+ op1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (op1) == SCOPE_REF)
+ op1 = tsubst_qualified_id (op1, args, complain, in_decl,
+ /*done=*/false, /*address_p=*/false);
+ else
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ /* Remember that there was a reference to this entity. */
+ if (DECL_P (op1))
+ mark_used (op1);
+ return grok_array_decl (op1,
+ tsubst_copy_and_build (TREE_OPERAND (t, 1),
+ args, complain,
+ in_decl));
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
case ARROW_EXPR:
- return build_x_arrow
- (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+ op1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (op1) == SCOPE_REF)
+ op1 = tsubst_qualified_id (op1, args, complain, in_decl,
+ /*done=*/false, /*address_p=*/false);
+ else
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+ /* Remember that there was a reference to this entity. */
+ if (DECL_P (op1))
+ mark_used (op1);
+ return build_x_arrow (op1);
case NEW_EXPR:
return build_new
abort ();
}
- case METHOD_CALL_EXPR:
+ case CALL_EXPR:
{
- tree method
- = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
-
- if (TREE_CODE (method) == SCOPE_REF)
+ tree function;
+ tree call_args;
+ tree koenig_name;
+ bool qualified_p;
+
+ function = TREE_OPERAND (t, 0);
+ if (TREE_CODE (function) == LOOKUP_EXPR
+ && !LOOKUP_EXPR_GLOBAL (function))
+ koenig_name = TREE_OPERAND (function, 0);
+ else
+ koenig_name = NULL_TREE;
+ if (TREE_CODE (function) == SCOPE_REF)
{
- tree name = TREE_OPERAND (method, 1);
-
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- name = build_nt (TEMPLATE_ID_EXPR,
- TREE_OPERAND (name, 0),
- TREE_OPERAND (name, 1));
-
- return build_scoped_method_call
- (tsubst_copy_and_build
- (TREE_OPERAND (t, 1), args, complain, in_decl),
- TREE_OPERAND (method, 0),
- name,
- tsubst_copy_and_build
- (TREE_OPERAND (t, 2), args, complain, in_decl));
+ qualified_p = true;
+ function = tsubst_qualified_id (function, args, complain, in_decl,
+ /*done=*/false,
+ /*address_p=*/false);
}
- else
+ else
{
- /* We can get a TEMPLATE_ID_EXPR here on code like:
-
- x->f<2>();
-
- so we must resolve that. However, we can also get things
- like a BIT_NOT_EXPR here, when referring to a destructor,
- and things like that are not correctly resolved by this
- function so just use it when we really need it. */
- if (TREE_CODE (method) == TEMPLATE_ID_EXPR)
- method = lookup_template_function
- (TREE_OPERAND (method, 0),
- TREE_OPERAND (method, 1));
-
- return build_method_call
- (tsubst_copy_and_build
- (TREE_OPERAND (t, 1), args, complain, in_decl),
- method,
- tsubst_copy_and_build
- (TREE_OPERAND (t, 2), args, complain, in_decl),
- NULL_TREE, LOOKUP_NORMAL);
+ qualified_p = (TREE_CODE (function) == COMPONENT_REF
+ && (TREE_CODE (TREE_OPERAND (function, 1))
+ == SCOPE_REF));
+ function = tsubst_copy_and_build (function, args, complain,
+ in_decl);
+ function = convert_from_reference (function);
}
- }
- case CALL_EXPR:
- {
- tree function, copy_args;
+ /* Remember that there was a reference to this entity. */
+ if (DECL_P (function))
+ mark_used (function);
- function = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
- copy_args = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
+ call_args = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
complain, in_decl);
if (BASELINK_P (function))
- return build_call_from_tree (function, copy_args, 1);
- else if (TREE_CODE (function) == SCOPE_REF)
- {
- tree name = TREE_OPERAND (function, 1);
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- name = build_nt (TEMPLATE_ID_EXPR,
- TREE_OPERAND (name, 0),
- build_expr_from_tree (TREE_OPERAND (name, 1)));
-
- function = resolve_scoped_fn_name (TREE_OPERAND (function, 0),
- name);
-
- return build_call_from_tree (function, copy_args, 1);
- }
+ return build_call_from_tree (function, call_args, 1);
else
{
- tree name = function;
- tree id;
-
- if (copy_args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
- && !LOOKUP_EXPR_GLOBAL (name)
- && (TREE_CODE ((id = TREE_OPERAND (name, 0)))
- == IDENTIFIER_NODE)
- && (!current_class_type
- || !lookup_member (current_class_type, id, 0, false)))
- {
- /* Do Koenig lookup if there are no class members. */
- name = do_identifier (id, copy_args);
- }
- else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
- || ! really_overloaded_fn (name))
- name = build_expr_from_tree (name);
-
- if (TREE_CODE (name) == OFFSET_REF)
- return build_offset_ref_call_from_tree (name, copy_args);
- if (TREE_CODE (name) == COMPONENT_REF)
- return finish_object_call_expr (TREE_OPERAND (name, 1),
- TREE_OPERAND (name, 0),
- copy_args);
- name = convert_from_reference (name);
- return build_call_from_tree (name, copy_args,
- /*disallow_virtual=*/false);
+ if (call_args != NULL_TREE && koenig_name)
+ function = lookup_arg_dependent (koenig_name,
+ function,
+ call_args);
+
+ if (TREE_CODE (function) == OFFSET_REF)
+ return build_offset_ref_call_from_tree (function, call_args);
+ if (TREE_CODE (function) == COMPONENT_REF)
+ return (build_new_method_call
+ (TREE_OPERAND (function, 0),
+ TREE_OPERAND (function, 1),
+ call_args, NULL_TREE,
+ qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
+ return finish_call_expr (function, call_args,
+ /*disallow_virtual=*/qualified_p);
}
}
case COMPONENT_REF:
{
- tree object =
- tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl);
- tree member =
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ tree object;
+ tree member;
+
+ object = TREE_OPERAND (t, 0);
+ if (TREE_CODE (object) == SCOPE_REF)
+ object = tsubst_qualified_id (object, args, complain, in_decl,
+ /*done=*/false, /*address_p=*/false);
+ else
+ object = tsubst_copy_and_build (object, args, complain, in_decl);
+
+ /* Remember that there was a reference to this entity. */
+ if (DECL_P (object))
+ mark_used (object);
+
+ member = TREE_OPERAND (t, 1);
+ if (BASELINK_P (member))
+ member = tsubst_baselink (member,
+ non_reference (TREE_TYPE (object)),
+ args, complain, in_decl);
+ else
+ member = tsubst_copy (member, args, complain, in_decl);
if (!CLASS_TYPE_P (TREE_TYPE (object)))
{
args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
member = lookup_qualified_name (TREE_OPERAND (member, 0),
tmpl,
- /*is_type=*/0,
- /*flags=*/0);
+ /*is_type=*/0);
if (BASELINK_P (member))
BASELINK_FUNCTIONS (member)
= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
case VAR_DECL:
- return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
+ if (args)
+ t = tsubst_copy (t, args, complain, in_decl);
+ return convert_from_reference (t);
case VA_ARG_EXPR:
return build_x_va_arg
with an expression that is value-dependent. */
if (TREE_CODE (expression) == VAR_DECL
&& DECL_INITIAL (expression)
- && (CP_INTEGRAL_TYPE_P (TREE_TYPE (expression))
- || TREE_CODE (TREE_TYPE (expression)) == ENUMERAL_TYPE)
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (expression)
&& value_dependent_expression_p (DECL_INITIAL (expression)))
return true;
/* These expressions are value-dependent if the type to which the