mirror of git://gcc.gnu.org/git/gcc.git
fold-const.c (make_range): Do not access operand 1 for a zero-operand operator.
* fold-const.c (make_range): Do not access operand 1 for a zero-operand operator. 2003-07-08 Mark Mitchell <mark@codesourcery.com> * cp-tree.def (NON_DEPENDENT_EXPR): New node. * cp-tree.h (build_call_from_tree): Remove. (build_member_call): Likewise. (dependent_template_arg_p): Remove. (any_dependent_template_arguments_p): New function. (dependent_template_id_p): Likewise. (any_type_dependent_arguments_p): Likewise. (build_non_dependent_expr): Likewise. (build_non_dependent_args): Likewise. (build_x_compound_expr): Adjust prototype. * call.c (build_new_method_call): Handle non-dependent expressions correctly. * decl2.c (grok_array_decl): Likewise. (build_offset_ref_call_from_tree): Likewise. (build_call_from_tree): Remove. * error.c (dump_decl): Handle NON_DEPENDENT_EXPR. (dump_expr): Likewise. * init.c (build_member_call): Remove. * mangle.c (write_expression): Update handling for template-ids. * parser.c (cp_parser_primary_expression): Use any_dependent_template_arguments_p. Update constant-expression handling. (cp_parser_postfix_expression): Use any_type_dependent_arguments_p. Simplify call processing. (cp_parser_unary_expression): Simplify. (cp_parser_expression): Adjust for changes to build_x_compound_expr. (cp_parser_template_argument): Implement standard-conforming parsing of non-type template arguments. (cp_parser_direct_declarator): Use cp_parser_fold_non_dependent_expr. (cp_parser_fold_non_dependent_expr): New function. (cp_parser_next_token_ends_template_argument_p): Likewise. * pt.c (convert_template_argument): Do not call maybe_fold_nontype_arg. (tsubst_baselink): Likewise. (tsubst_copy_and_build): Share common code. Make sizeof/alignof processing work correctly for non-dependent expressions. Adjust handling of COMPOUND_EXPR. Simplify call processing. (value_dependent_expression_p): Deal with functional casts and sizeof/alignof correctly. (type_dependent_expression_p): Handle overloaded functions. (any_type_dependent_arguments_p): New function. (any_dependent_template_arguments_p): Likewise. (dependent_template_p): Treat SCOPE_REFs as dependent. (dependent_template_id_p): Simplify. (build_non_dependent_expr): New function. (build_non_dependent_args): Likewise. * semantics.c (finish_stmt_expr): Don't make dependent statement-expresions have void type. (finish_call_expr): Handle non-dependent expressions correctly. * tree.c (lvalue_p_1): Treat NON_DEPENDENT_EXPRs as lvalues. * typeck.c (cxx_sizeof_or_alignof_type): Give the expression type size_t, even in templates. (expr_sizeof): Likewise. (finish_class_member_access_expr): Handle non-dependent expressions correctly. (build_x_indirect_ref): Likewise. (build_x_binary_op): Likewise. (build_x_unary_op): Likewise. (build_x_conditional_expr): Likewise. (build_x_compound_expr): Likewise. * typeck2.c (build_x_arrow): Likewise. 2003-07-08 Mark Mitchell <mark@codesourcery.com> * g++.dg/abi/mangle17.C: Make sure template expressions are dependent. * g++.dg/abi/mangle4.C: Mark erroneous casts. * g++.dg/debug/debug7.C: Mark erronous new-declarator. * g++.dg/opt/stack1.C: Remove erroneous code. * g++.dg/parse/template7.C: New test. * g++.dg/template/dependent-expr1.C: Mark erroneous code. * g++.old-deja/g++.pt/crash4.C: Likewise. 2003-07-09 Mark Mitchell <mark@codesourcery.com> * gcj/array.h (JvPrimClass): Don't parenthesize the output. From-SVN: r69130
This commit is contained in:
parent
844c00ed16
commit
d17811fd1a
|
@ -1,3 +1,8 @@
|
||||||
|
2003-07-08 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
* fold-const.c (make_range): Do not access operand 1 for a
|
||||||
|
zero-operand operator.
|
||||||
|
|
||||||
2003-07-09 Neil Booth <neil@daikokuya.co.uk>
|
2003-07-09 Neil Booth <neil@daikokuya.co.uk>
|
||||||
|
|
||||||
* toplev.c (warn_dummy, W_options): Die.
|
* toplev.c (warn_dummy, W_options): Die.
|
||||||
|
|
|
@ -1,3 +1,70 @@
|
||||||
|
2003-07-08 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
* cp-tree.def (NON_DEPENDENT_EXPR): New node.
|
||||||
|
* cp-tree.h (build_call_from_tree): Remove.
|
||||||
|
(build_member_call): Likewise.
|
||||||
|
(dependent_template_arg_p): Remove.
|
||||||
|
(any_dependent_template_arguments_p): New function.
|
||||||
|
(dependent_template_id_p): Likewise.
|
||||||
|
(any_type_dependent_arguments_p): Likewise.
|
||||||
|
(build_non_dependent_expr): Likewise.
|
||||||
|
(build_non_dependent_args): Likewise.
|
||||||
|
(build_x_compound_expr): Adjust prototype.
|
||||||
|
* call.c (build_new_method_call): Handle non-dependent expressions
|
||||||
|
correctly.
|
||||||
|
* decl2.c (grok_array_decl): Likewise.
|
||||||
|
(build_offset_ref_call_from_tree): Likewise.
|
||||||
|
(build_call_from_tree): Remove.
|
||||||
|
* error.c (dump_decl): Handle NON_DEPENDENT_EXPR.
|
||||||
|
(dump_expr): Likewise.
|
||||||
|
* init.c (build_member_call): Remove.
|
||||||
|
* mangle.c (write_expression): Update handling for template-ids.
|
||||||
|
* parser.c (cp_parser_primary_expression): Use
|
||||||
|
any_dependent_template_arguments_p. Update constant-expression
|
||||||
|
handling.
|
||||||
|
(cp_parser_postfix_expression): Use
|
||||||
|
any_type_dependent_arguments_p. Simplify call processing.
|
||||||
|
(cp_parser_unary_expression): Simplify.
|
||||||
|
(cp_parser_expression): Adjust for changes to
|
||||||
|
build_x_compound_expr.
|
||||||
|
(cp_parser_template_argument): Implement standard-conforming
|
||||||
|
parsing of non-type template arguments.
|
||||||
|
(cp_parser_direct_declarator): Use
|
||||||
|
cp_parser_fold_non_dependent_expr.
|
||||||
|
(cp_parser_fold_non_dependent_expr): New function.
|
||||||
|
(cp_parser_next_token_ends_template_argument_p): Likewise.
|
||||||
|
* pt.c (convert_template_argument): Do not call
|
||||||
|
maybe_fold_nontype_arg.
|
||||||
|
(tsubst_baselink): Likewise.
|
||||||
|
(tsubst_copy_and_build): Share common code. Make sizeof/alignof
|
||||||
|
processing work correctly for non-dependent expressions. Adjust
|
||||||
|
handling of COMPOUND_EXPR. Simplify call processing.
|
||||||
|
(value_dependent_expression_p): Deal with functional casts and
|
||||||
|
sizeof/alignof correctly.
|
||||||
|
(type_dependent_expression_p): Handle overloaded functions.
|
||||||
|
(any_type_dependent_arguments_p): New function.
|
||||||
|
(any_dependent_template_arguments_p): Likewise.
|
||||||
|
(dependent_template_p): Treat SCOPE_REFs as dependent.
|
||||||
|
(dependent_template_id_p): Simplify.
|
||||||
|
(build_non_dependent_expr): New function.
|
||||||
|
(build_non_dependent_args): Likewise.
|
||||||
|
* semantics.c (finish_stmt_expr): Don't make dependent
|
||||||
|
statement-expresions have void type.
|
||||||
|
(finish_call_expr): Handle non-dependent expressions
|
||||||
|
correctly.
|
||||||
|
* tree.c (lvalue_p_1): Treat NON_DEPENDENT_EXPRs as lvalues.
|
||||||
|
* typeck.c (cxx_sizeof_or_alignof_type): Give the expression
|
||||||
|
type size_t, even in templates.
|
||||||
|
(expr_sizeof): Likewise.
|
||||||
|
(finish_class_member_access_expr): Handle non-dependent expressions
|
||||||
|
correctly.
|
||||||
|
(build_x_indirect_ref): Likewise.
|
||||||
|
(build_x_binary_op): Likewise.
|
||||||
|
(build_x_unary_op): Likewise.
|
||||||
|
(build_x_conditional_expr): Likewise.
|
||||||
|
(build_x_compound_expr): Likewise.
|
||||||
|
* typeck2.c (build_x_arrow): Likewise.
|
||||||
|
|
||||||
Wed Jul 9 02:28:39 CEST 2003 Jan Hubicka <jh@suse.cz>
|
Wed Jul 9 02:28:39 CEST 2003 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
* cp-lang.c (LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS): New.
|
* cp-lang.c (LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS): New.
|
||||||
|
@ -210,13 +277,13 @@ Wed Jul 9 02:28:39 CEST 2003 Jan Hubicka <jh@suse.cz>
|
||||||
(build_conditional_expr): Likewise.
|
(build_conditional_expr): Likewise.
|
||||||
(build_new_method_call): Likewise.
|
(build_new_method_call): Likewise.
|
||||||
* cp-tree.def (OFFSET_REF): Update documentation.
|
* cp-tree.def (OFFSET_REF): Update documentation.
|
||||||
(cp_convert_to_pointer): Update handling of conversions from
|
* cvt.c (cp_convert_to_pointer): Update handling of conversions from
|
||||||
pointers to members to pointers.
|
pointers to members to pointers.
|
||||||
(ocp_convert): Do not call resolve_offset_ref.
|
(ocp_convert): Do not call resolve_offset_ref.
|
||||||
(convert_to_void): Likewise.
|
(convert_to_void): Likewise.
|
||||||
(build_expr_type_conversion): Likewise.
|
(build_expr_type_conversion): Likewise.
|
||||||
(delete_sanity): Likewise.
|
* decl2.c (delete_sanity): Likewise.
|
||||||
(resolve_offset_ref): Simplify greatly.
|
* init.c (resolve_offset_ref): Simplify greatly.
|
||||||
(build_vec_delete): Do not call resolve_offset_ref.
|
(build_vec_delete): Do not call resolve_offset_ref.
|
||||||
* parser.c (cp_parser_postfix_expression): Call resolve_offset_ref
|
* parser.c (cp_parser_postfix_expression): Call resolve_offset_ref
|
||||||
if appropriate.
|
if appropriate.
|
||||||
|
|
|
@ -325,8 +325,7 @@ build_call (tree function, tree parms)
|
||||||
|
|
||||||
BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE
|
BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE
|
||||||
down to the real instance type to use for access checking. We need this
|
down to the real instance type to use for access checking. We need this
|
||||||
information to get protected accesses correct. This parameter is used
|
information to get protected accesses correct.
|
||||||
by build_member_call.
|
|
||||||
|
|
||||||
FLAGS is the logical disjunction of zero or more LOOKUP_
|
FLAGS is the logical disjunction of zero or more LOOKUP_
|
||||||
flags. See cp-tree.h for more info.
|
flags. See cp-tree.h for more info.
|
||||||
|
@ -4883,6 +4882,9 @@ build_new_method_call (tree instance, tree fns, tree args,
|
||||||
tree class_type;
|
tree class_type;
|
||||||
int template_only = 0;
|
int template_only = 0;
|
||||||
bool any_viable_p;
|
bool any_viable_p;
|
||||||
|
tree orig_instance;
|
||||||
|
tree orig_fns;
|
||||||
|
tree orig_args;
|
||||||
|
|
||||||
my_friendly_assert (instance != NULL_TREE, 20020729);
|
my_friendly_assert (instance != NULL_TREE, 20020729);
|
||||||
|
|
||||||
|
@ -4891,6 +4893,20 @@ build_new_method_call (tree instance, tree fns, tree args,
|
||||||
|| args == error_mark_node)
|
|| args == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
|
orig_instance = instance;
|
||||||
|
orig_fns = fns;
|
||||||
|
orig_args = args;
|
||||||
|
|
||||||
|
if (processing_template_decl)
|
||||||
|
{
|
||||||
|
instance = build_non_dependent_expr (instance);
|
||||||
|
if (!BASELINK_P (fns)
|
||||||
|
&& TREE_CODE (fns) != PSEUDO_DTOR_EXPR
|
||||||
|
&& TREE_TYPE (fns) != unknown_type_node)
|
||||||
|
fns = build_non_dependent_expr (fns);
|
||||||
|
args = build_non_dependent_args (orig_args);
|
||||||
|
}
|
||||||
|
|
||||||
/* Process the argument list. */
|
/* Process the argument list. */
|
||||||
user_args = args;
|
user_args = args;
|
||||||
args = resolve_args (args);
|
args = resolve_args (args);
|
||||||
|
@ -5068,6 +5084,13 @@ build_new_method_call (tree instance, tree fns, tree args,
|
||||||
call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
|
call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (processing_template_decl && call != error_mark_node)
|
||||||
|
return build_min (CALL_EXPR,
|
||||||
|
TREE_TYPE (call),
|
||||||
|
build_min_nt (COMPONENT_REF,
|
||||||
|
orig_instance,
|
||||||
|
orig_fns),
|
||||||
|
orig_args);
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,6 +238,16 @@ DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", 'e', 2)
|
||||||
DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
|
DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
|
||||||
DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", 'e', 3)
|
DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", 'e', 3)
|
||||||
|
|
||||||
|
/* A placeholder for an expression that is not type-dependent, but
|
||||||
|
does occur in a template. When an expression that is not
|
||||||
|
type-dependent appears in a larger expression, we must compute the
|
||||||
|
type of that larger expression. That computation would normally
|
||||||
|
modify the original expression, which would change the mangling of
|
||||||
|
that expression if it appeared in a template argument list. In
|
||||||
|
that situation, we create a NON_DEPENDENT_EXPR to take the place of
|
||||||
|
the original expression. */
|
||||||
|
DEFTREECODE (NON_DEPENDENT_EXPR, "non_dependent_expr", 'e', 0)
|
||||||
|
|
||||||
/* CTOR_INITIALIZER is a placeholder in template code for a call to
|
/* CTOR_INITIALIZER is a placeholder in template code for a call to
|
||||||
setup_vtbl_pointer (and appears in all functions, not just ctors). */
|
setup_vtbl_pointer (and appears in all functions, not just ctors). */
|
||||||
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 1)
|
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 1)
|
||||||
|
|
|
@ -215,6 +215,7 @@ struct diagnostic_context;
|
||||||
|
|
||||||
#define abi_version_at_least(N) \
|
#define abi_version_at_least(N) \
|
||||||
(flag_abi_version == 0 || flag_abi_version >= (N))
|
(flag_abi_version == 0 || flag_abi_version >= (N))
|
||||||
|
|
||||||
|
|
||||||
/* Language-dependent contents of an identifier. */
|
/* Language-dependent contents of an identifier. */
|
||||||
|
|
||||||
|
@ -3775,7 +3776,6 @@ extern void import_export_tinfo (tree, tree, bool);
|
||||||
extern void finish_file (void);
|
extern void finish_file (void);
|
||||||
extern tree build_cleanup (tree);
|
extern tree build_cleanup (tree);
|
||||||
extern tree build_offset_ref_call_from_tree (tree, tree);
|
extern tree build_offset_ref_call_from_tree (tree, tree);
|
||||||
extern tree build_call_from_tree (tree, tree, bool);
|
|
||||||
extern void set_decl_namespace (tree, tree, bool);
|
extern void set_decl_namespace (tree, tree, bool);
|
||||||
extern tree current_decl_namespace (void);
|
extern tree current_decl_namespace (void);
|
||||||
extern void push_decl_namespace (tree);
|
extern void push_decl_namespace (tree);
|
||||||
|
@ -3853,7 +3853,6 @@ extern int is_aggr_type (tree, int);
|
||||||
extern tree get_aggr_from_typedef (tree, int);
|
extern tree get_aggr_from_typedef (tree, int);
|
||||||
extern tree get_type_value (tree);
|
extern tree get_type_value (tree);
|
||||||
extern tree build_zero_init (tree, tree, bool);
|
extern tree build_zero_init (tree, tree, bool);
|
||||||
extern tree build_member_call (tree, tree, tree);
|
|
||||||
extern tree build_offset_ref (tree, tree);
|
extern tree build_offset_ref (tree, tree);
|
||||||
extern tree resolve_offset_ref (tree);
|
extern tree resolve_offset_ref (tree);
|
||||||
extern tree build_new (tree, tree, tree, int);
|
extern tree build_new (tree, tree, tree, int);
|
||||||
|
@ -3974,12 +3973,16 @@ extern tree current_instantiation (void);
|
||||||
extern tree maybe_get_template_decl_from_type_decl (tree);
|
extern tree maybe_get_template_decl_from_type_decl (tree);
|
||||||
extern int processing_template_parmlist;
|
extern int processing_template_parmlist;
|
||||||
extern bool dependent_type_p (tree);
|
extern bool dependent_type_p (tree);
|
||||||
extern bool dependent_template_arg_p (tree);
|
extern bool any_dependent_template_arguments_p (tree);
|
||||||
extern bool dependent_template_p (tree);
|
extern bool dependent_template_p (tree);
|
||||||
|
extern bool dependent_template_id_p (tree, tree);
|
||||||
extern bool type_dependent_expression_p (tree);
|
extern bool type_dependent_expression_p (tree);
|
||||||
|
extern bool any_type_dependent_arguments_p (tree);
|
||||||
extern bool value_dependent_expression_p (tree);
|
extern bool value_dependent_expression_p (tree);
|
||||||
extern tree resolve_typename_type (tree, bool);
|
extern tree resolve_typename_type (tree, bool);
|
||||||
extern tree template_for_substitution (tree);
|
extern tree template_for_substitution (tree);
|
||||||
|
extern tree build_non_dependent_expr (tree);
|
||||||
|
extern tree build_non_dependent_args (tree);
|
||||||
|
|
||||||
/* in repo.c */
|
/* in repo.c */
|
||||||
extern void repo_template_used (tree);
|
extern void repo_template_used (tree);
|
||||||
|
@ -4267,7 +4270,7 @@ extern tree build_x_binary_op (enum tree_code, tree, tree);
|
||||||
extern tree build_x_unary_op (enum tree_code, tree);
|
extern tree build_x_unary_op (enum tree_code, tree);
|
||||||
extern tree unary_complex_lvalue (enum tree_code, tree);
|
extern tree unary_complex_lvalue (enum tree_code, tree);
|
||||||
extern tree build_x_conditional_expr (tree, tree, tree);
|
extern tree build_x_conditional_expr (tree, tree, tree);
|
||||||
extern tree build_x_compound_expr (tree);
|
extern tree build_x_compound_expr (tree, tree);
|
||||||
extern tree build_compound_expr (tree);
|
extern tree build_compound_expr (tree);
|
||||||
extern tree build_static_cast (tree, tree);
|
extern tree build_static_cast (tree, tree);
|
||||||
extern tree build_reinterpret_cast (tree, tree);
|
extern tree build_reinterpret_cast (tree, tree);
|
||||||
|
|
200
gcc/cp/decl2.c
200
gcc/cp/decl2.c
|
@ -398,59 +398,77 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
|
||||||
tree
|
tree
|
||||||
grok_array_decl (tree array_expr, tree index_exp)
|
grok_array_decl (tree array_expr, tree index_exp)
|
||||||
{
|
{
|
||||||
tree type = TREE_TYPE (array_expr);
|
tree type;
|
||||||
tree p1, p2, i1, i2;
|
tree expr;
|
||||||
|
tree orig_array_expr = array_expr;
|
||||||
|
tree orig_index_exp = index_exp;
|
||||||
|
|
||||||
if (type == error_mark_node || index_exp == error_mark_node)
|
if (error_operand_p (array_expr) || error_operand_p (index_exp))
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE,
|
{
|
||||||
array_expr, index_exp);
|
if (type_dependent_expression_p (array_expr)
|
||||||
|
|| type_dependent_expression_p (index_exp))
|
||||||
|
return build_min_nt (ARRAY_REF, array_expr, index_exp);
|
||||||
|
array_expr = build_non_dependent_expr (array_expr);
|
||||||
|
index_exp = build_non_dependent_expr (index_exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
type = TREE_TYPE (array_expr);
|
||||||
my_friendly_assert (type, 20030626);
|
my_friendly_assert (type, 20030626);
|
||||||
|
|
||||||
type = non_reference (type);
|
type = non_reference (type);
|
||||||
|
|
||||||
/* If they have an `operator[]', use that. */
|
/* If they have an `operator[]', use that. */
|
||||||
if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
|
if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
|
||||||
return build_new_op (ARRAY_REF, LOOKUP_NORMAL,
|
expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
|
||||||
array_expr, index_exp, NULL_TREE);
|
array_expr, index_exp, NULL_TREE);
|
||||||
|
|
||||||
/* Otherwise, create an ARRAY_REF for a pointer or array type. It
|
|
||||||
is a little-known fact that, if `a' is an array and `i' is an
|
|
||||||
int, you can write `i[a]', which means the same thing as `a[i]'. */
|
|
||||||
|
|
||||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
|
||||||
p1 = array_expr;
|
|
||||||
else
|
|
||||||
p1 = build_expr_type_conversion (WANT_POINTER, array_expr, false);
|
|
||||||
|
|
||||||
if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE)
|
|
||||||
p2 = index_exp;
|
|
||||||
else
|
|
||||||
p2 = build_expr_type_conversion (WANT_POINTER, index_exp, false);
|
|
||||||
|
|
||||||
i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, false);
|
|
||||||
i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, false);
|
|
||||||
|
|
||||||
if ((p1 && i2) && (i1 && p2))
|
|
||||||
error ("ambiguous conversion for array subscript");
|
|
||||||
|
|
||||||
if (p1 && i2)
|
|
||||||
array_expr = p1, index_exp = i2;
|
|
||||||
else if (i1 && p2)
|
|
||||||
array_expr = p2, index_exp = i1;
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error ("invalid types `%T[%T]' for array subscript",
|
tree p1, p2, i1, i2;
|
||||||
type, TREE_TYPE (index_exp));
|
|
||||||
return error_mark_node;
|
/* Otherwise, create an ARRAY_REF for a pointer or array type.
|
||||||
|
It is a little-known fact that, if `a' is an array and `i' is
|
||||||
|
an int, you can write `i[a]', which means the same thing as
|
||||||
|
`a[i]'. */
|
||||||
|
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||||
|
p1 = array_expr;
|
||||||
|
else
|
||||||
|
p1 = build_expr_type_conversion (WANT_POINTER, array_expr, false);
|
||||||
|
|
||||||
|
if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE)
|
||||||
|
p2 = index_exp;
|
||||||
|
else
|
||||||
|
p2 = build_expr_type_conversion (WANT_POINTER, index_exp, false);
|
||||||
|
|
||||||
|
i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr,
|
||||||
|
false);
|
||||||
|
i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp,
|
||||||
|
false);
|
||||||
|
|
||||||
|
if ((p1 && i2) && (i1 && p2))
|
||||||
|
error ("ambiguous conversion for array subscript");
|
||||||
|
|
||||||
|
if (p1 && i2)
|
||||||
|
array_expr = p1, index_exp = i2;
|
||||||
|
else if (i1 && p2)
|
||||||
|
array_expr = p2, index_exp = i1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error ("invalid types `%T[%T]' for array subscript",
|
||||||
|
type, TREE_TYPE (index_exp));
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_expr == error_mark_node || index_exp == error_mark_node)
|
||||||
|
error ("ambiguous conversion for array subscript");
|
||||||
|
|
||||||
|
expr = build_array_ref (array_expr, index_exp);
|
||||||
}
|
}
|
||||||
|
if (processing_template_decl && expr != error_mark_node)
|
||||||
if (array_expr == error_mark_node || index_exp == error_mark_node)
|
return build_min (ARRAY_REF, TREE_TYPE (expr), orig_array_expr,
|
||||||
error ("ambiguous conversion for array subscript");
|
orig_index_exp);
|
||||||
|
return expr;
|
||||||
return build_array_ref (array_expr, index_exp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given the cast expression EXP, checking out its validity. Either return
|
/* Given the cast expression EXP, checking out its validity. Either return
|
||||||
|
@ -2949,8 +2967,37 @@ tree
|
||||||
build_offset_ref_call_from_tree (tree fn, tree args)
|
build_offset_ref_call_from_tree (tree fn, tree args)
|
||||||
{
|
{
|
||||||
tree object_addr;
|
tree object_addr;
|
||||||
|
tree orig_fn;
|
||||||
|
tree orig_args;
|
||||||
|
tree expr;
|
||||||
|
|
||||||
my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725);
|
orig_fn = fn;
|
||||||
|
orig_args = args;
|
||||||
|
|
||||||
|
if (processing_template_decl)
|
||||||
|
{
|
||||||
|
tree object;
|
||||||
|
tree object_type;
|
||||||
|
|
||||||
|
my_friendly_assert (TREE_CODE (fn) == DOTSTAR_EXPR
|
||||||
|
|| TREE_CODE (fn) == MEMBER_REF,
|
||||||
|
20030708);
|
||||||
|
if (type_dependent_expression_p (fn)
|
||||||
|
|| any_type_dependent_arguments_p (args))
|
||||||
|
return build_min_nt (CALL_EXPR, fn, args);
|
||||||
|
|
||||||
|
/* Transform the arguments and add the implicit "this"
|
||||||
|
parameter. That must be done before the FN is transformed
|
||||||
|
because we depend on the form of FN. */
|
||||||
|
args = build_non_dependent_args (args);
|
||||||
|
object_type = TREE_TYPE (TREE_OPERAND (fn, 0));
|
||||||
|
if (TREE_CODE (fn) == DOTSTAR_EXPR)
|
||||||
|
object_type = build_pointer_type (non_reference (object_type));
|
||||||
|
object = build (NON_DEPENDENT_EXPR, object_type);
|
||||||
|
args = tree_cons (NULL_TREE, object, args);
|
||||||
|
/* Now that the arguments are done, transform FN. */
|
||||||
|
fn = build_non_dependent_expr (fn);
|
||||||
|
}
|
||||||
|
|
||||||
/* A qualified name corresponding to a bound pointer-to-member is
|
/* A qualified name corresponding to a bound pointer-to-member is
|
||||||
represented as an OFFSET_REF:
|
represented as an OFFSET_REF:
|
||||||
|
@ -2958,79 +3005,18 @@ build_offset_ref_call_from_tree (tree fn, tree args)
|
||||||
struct B { void g(); };
|
struct B { void g(); };
|
||||||
void (B::*p)();
|
void (B::*p)();
|
||||||
void B::g() { (this->*p)(); } */
|
void B::g() { (this->*p)(); } */
|
||||||
if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL)
|
if (TREE_CODE (fn) == OFFSET_REF)
|
||||||
/* This case should now be handled elsewhere. */
|
|
||||||
abort ();
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0);
|
object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0);
|
||||||
fn = TREE_OPERAND (fn, 1);
|
fn = TREE_OPERAND (fn, 1);
|
||||||
fn = get_member_function_from_ptrfunc (&object_addr, fn);
|
fn = get_member_function_from_ptrfunc (&object_addr, fn);
|
||||||
args = tree_cons (NULL_TREE, object_addr, args);
|
args = tree_cons (NULL_TREE, object_addr, args);
|
||||||
}
|
}
|
||||||
return build_function_call (fn, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FN indicates the function to call. Name resolution has been
|
expr = build_function_call (fn, args);
|
||||||
performed on FN. ARGS are the arguments to the function. They
|
if (processing_template_decl && expr != error_mark_node)
|
||||||
have already been semantically analyzed. DISALLOW_VIRTUAL is true
|
return build_min (CALL_EXPR, TREE_TYPE (expr), orig_fn, orig_args);
|
||||||
if the function call should be determined at compile time, even if
|
return expr;
|
||||||
FN is virtual. */
|
|
||||||
|
|
||||||
tree
|
|
||||||
build_call_from_tree (tree fn, tree args, bool disallow_virtual)
|
|
||||||
{
|
|
||||||
tree template_args;
|
|
||||||
tree template_id;
|
|
||||||
tree f;
|
|
||||||
|
|
||||||
/* Check to see that name lookup has already been performed. */
|
|
||||||
my_friendly_assert (TREE_CODE (fn) != OFFSET_REF, 20020725);
|
|
||||||
my_friendly_assert (TREE_CODE (fn) != SCOPE_REF, 20020725);
|
|
||||||
|
|
||||||
/* In the future all of this should be eliminated. Instead,
|
|
||||||
name-lookup for a member function should simply return a
|
|
||||||
baselink, instead of a FUNCTION_DECL, TEMPLATE_DECL, or
|
|
||||||
TEMPLATE_ID_EXPR. */
|
|
||||||
|
|
||||||
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
|
|
||||||
{
|
|
||||||
template_id = fn;
|
|
||||||
template_args = TREE_OPERAND (fn, 1);
|
|
||||||
fn = TREE_OPERAND (fn, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
template_id = NULL_TREE;
|
|
||||||
template_args = NULL_TREE;
|
|
||||||
}
|
|
||||||
|
|
||||||
f = (TREE_CODE (fn) == OVERLOAD) ? get_first_fn (fn) : fn;
|
|
||||||
/* Make sure we have a baselink (rather than simply a
|
|
||||||
FUNCTION_DECL) for a member function. */
|
|
||||||
if (current_class_type
|
|
||||||
&& ((TREE_CODE (f) == FUNCTION_DECL
|
|
||||||
&& DECL_FUNCTION_MEMBER_P (f))
|
|
||||||
|| (DECL_FUNCTION_TEMPLATE_P (f)
|
|
||||||
&& DECL_FUNCTION_MEMBER_P (f))))
|
|
||||||
{
|
|
||||||
f = lookup_member (current_class_type, DECL_NAME (f),
|
|
||||||
/*protect=*/1, /*want_type=*/false);
|
|
||||||
if (f)
|
|
||||||
fn = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (template_id)
|
|
||||||
{
|
|
||||||
if (BASELINK_P (fn))
|
|
||||||
BASELINK_FUNCTIONS (fn) = build_nt (TEMPLATE_ID_EXPR,
|
|
||||||
BASELINK_FUNCTIONS (fn),
|
|
||||||
template_args);
|
|
||||||
else
|
|
||||||
fn = template_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return finish_call_expr (fn, args, disallow_virtual);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if ROOT (a namespace, class, or function) encloses
|
/* Returns true if ROOT (a namespace, class, or function) encloses
|
||||||
|
|
|
@ -988,6 +988,10 @@ dump_decl (tree t, int flags)
|
||||||
dump_decl (BASELINK_FUNCTIONS (t), flags);
|
dump_decl (BASELINK_FUNCTIONS (t), flags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NON_DEPENDENT_EXPR:
|
||||||
|
dump_expr (t, flags);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
sorry_for_unsupported_tree (t);
|
sorry_for_unsupported_tree (t);
|
||||||
/* Fallthrough to error. */
|
/* Fallthrough to error. */
|
||||||
|
@ -2028,7 +2032,11 @@ dump_expr (tree t, int flags)
|
||||||
dump_expr (get_first_fn (t), flags & ~TFF_EXPR_IN_PARENS);
|
dump_expr (get_first_fn (t), flags & ~TFF_EXPR_IN_PARENS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* else fall through */
|
case NON_DEPENDENT_EXPR:
|
||||||
|
output_add_string (scratch_buffer, "<expression of type ");
|
||||||
|
dump_type (TREE_TYPE (t), flags);
|
||||||
|
output_add_character (scratch_buffer, '>');
|
||||||
|
break;
|
||||||
|
|
||||||
/* This list is incomplete, but should suffice for now.
|
/* This list is incomplete, but should suffice for now.
|
||||||
It is very important that `sorry' does not call
|
It is very important that `sorry' does not call
|
||||||
|
|
151
gcc/cp/init.c
151
gcc/cp/init.c
|
@ -1337,157 +1337,6 @@ get_type_value (tree name)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This code could just as well go in `class.c', but is placed here for
|
|
||||||
modularity. */
|
|
||||||
|
|
||||||
/* For an expression of the form TYPE :: NAME (PARMLIST), build
|
|
||||||
the appropriate function call. */
|
|
||||||
|
|
||||||
tree
|
|
||||||
build_member_call (tree type, tree name, tree parmlist)
|
|
||||||
{
|
|
||||||
tree t;
|
|
||||||
tree method_name;
|
|
||||||
tree fns;
|
|
||||||
int dtor = 0;
|
|
||||||
tree basetype_path, decl;
|
|
||||||
|
|
||||||
if (TREE_CODE (name) == TEMPLATE_ID_EXPR
|
|
||||||
&& TREE_CODE (type) == NAMESPACE_DECL)
|
|
||||||
{
|
|
||||||
/* 'name' already refers to the decls from the namespace, since we
|
|
||||||
hit do_identifier for template_ids. */
|
|
||||||
method_name = TREE_OPERAND (name, 0);
|
|
||||||
/* FIXME: Since we don't do independent names right yet, the
|
|
||||||
name might also be a LOOKUP_EXPR. Once we resolve this to a
|
|
||||||
real decl earlier, this can go. This may happen during
|
|
||||||
tsubst'ing. */
|
|
||||||
if (TREE_CODE (method_name) == LOOKUP_EXPR)
|
|
||||||
{
|
|
||||||
method_name = lookup_namespace_name
|
|
||||||
(type, TREE_OPERAND (method_name, 0));
|
|
||||||
TREE_OPERAND (name, 0) = method_name;
|
|
||||||
}
|
|
||||||
my_friendly_assert (is_overloaded_fn (method_name), 980519);
|
|
||||||
return finish_call_expr (name, parmlist, /*disallow_virtual=*/true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DECL_P (name))
|
|
||||||
name = DECL_NAME (name);
|
|
||||||
|
|
||||||
if (TREE_CODE (type) == NAMESPACE_DECL)
|
|
||||||
return finish_call_expr (lookup_namespace_name (type, name),
|
|
||||||
parmlist,
|
|
||||||
/*disallow_virtual=*/true);
|
|
||||||
|
|
||||||
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
|
||||||
{
|
|
||||||
method_name = TREE_OPERAND (name, 0);
|
|
||||||
if (TREE_CODE (method_name) == COMPONENT_REF)
|
|
||||||
method_name = TREE_OPERAND (method_name, 1);
|
|
||||||
if (is_overloaded_fn (method_name))
|
|
||||||
method_name = DECL_NAME (OVL_CURRENT (method_name));
|
|
||||||
TREE_OPERAND (name, 0) = method_name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
method_name = name;
|
|
||||||
|
|
||||||
if (TREE_CODE (method_name) == BIT_NOT_EXPR)
|
|
||||||
{
|
|
||||||
method_name = TREE_OPERAND (method_name, 0);
|
|
||||||
dtor = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This shouldn't be here, and build_member_call shouldn't appear in
|
|
||||||
parse.y! (mrs) */
|
|
||||||
if (type && TREE_CODE (type) == IDENTIFIER_NODE
|
|
||||||
&& get_aggr_from_typedef (type, 0) == 0)
|
|
||||||
{
|
|
||||||
tree ns = lookup_name (type, 0);
|
|
||||||
if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
|
|
||||||
return finish_call_expr (lookup_namespace_name (ns, name),
|
|
||||||
parmlist,
|
|
||||||
/*disallow_virtual=*/true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == NULL_TREE || ! is_aggr_type (type, 1))
|
|
||||||
return error_mark_node;
|
|
||||||
|
|
||||||
/* An operator we did not like. */
|
|
||||||
if (name == NULL_TREE)
|
|
||||||
return error_mark_node;
|
|
||||||
|
|
||||||
if (dtor)
|
|
||||||
{
|
|
||||||
error ("cannot call destructor `%T::~%T' without object", type,
|
|
||||||
method_name);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
decl = maybe_dummy_object (type, &basetype_path);
|
|
||||||
|
|
||||||
fns = lookup_fnfields (basetype_path, method_name, 0);
|
|
||||||
if (fns)
|
|
||||||
{
|
|
||||||
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
|
||||||
BASELINK_FUNCTIONS (fns) = build_nt (TEMPLATE_ID_EXPR,
|
|
||||||
BASELINK_FUNCTIONS (fns),
|
|
||||||
TREE_OPERAND (name, 1));
|
|
||||||
return build_new_method_call (decl, fns, parmlist,
|
|
||||||
/*conversion_path=*/NULL_TREE,
|
|
||||||
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert 'this' to the specified type to disambiguate conversion
|
|
||||||
to the function's context. */
|
|
||||||
if (decl == current_class_ref
|
|
||||||
/* ??? this is wrong, but if this conversion is invalid we need to
|
|
||||||
defer it until we know whether we are calling a static or
|
|
||||||
non-static member function. Be conservative for now. */
|
|
||||||
&& ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
|
|
||||||
{
|
|
||||||
basetype_path = NULL_TREE;
|
|
||||||
decl = build_scoped_ref (decl, type, &basetype_path);
|
|
||||||
if (decl == error_mark_node)
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (constructor_name_p (method_name, type))
|
|
||||||
return build_functional_cast (type, parmlist);
|
|
||||||
if (TREE_CODE (name) == IDENTIFIER_NODE
|
|
||||||
&& ((t = lookup_field (TYPE_BINFO (type), name, 1, false))))
|
|
||||||
{
|
|
||||||
if (t == error_mark_node)
|
|
||||||
return error_mark_node;
|
|
||||||
if (TREE_CODE (t) == FIELD_DECL)
|
|
||||||
{
|
|
||||||
if (is_dummy_object (decl))
|
|
||||||
{
|
|
||||||
error ("invalid use of non-static field `%D'", t);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t);
|
|
||||||
}
|
|
||||||
else if (TREE_CODE (t) == VAR_DECL)
|
|
||||||
decl = t;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error ("invalid use of member `%D'", t);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
|
|
||||||
return build_new_op (CALL_EXPR, LOOKUP_NORMAL, decl,
|
|
||||||
parmlist, NULL_TREE);
|
|
||||||
return build_function_call (decl, parmlist);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error ("no method `%T::%D'", type, name);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build a reference to a member of an aggregate. This is not a
|
/* Build a reference to a member of an aggregate. This is not a
|
||||||
C++ `&', but really something which can have its address taken,
|
C++ `&', but really something which can have its address taken,
|
||||||
and then act as a pointer to member, for example TYPE :: FIELD
|
and then act as a pointer to member, for example TYPE :: FIELD
|
||||||
|
|
|
@ -2019,6 +2019,19 @@ write_expression (tree expr)
|
||||||
write_type (TREE_OPERAND (expr, 0));
|
write_type (TREE_OPERAND (expr, 0));
|
||||||
if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
|
if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
|
||||||
write_source_name (TREE_OPERAND (expr, 1));
|
write_source_name (TREE_OPERAND (expr, 1));
|
||||||
|
else if (TREE_CODE (TREE_OPERAND (expr, 1)) == TEMPLATE_ID_EXPR)
|
||||||
|
{
|
||||||
|
tree template_id;
|
||||||
|
tree name;
|
||||||
|
|
||||||
|
template_id = TREE_OPERAND (expr, 1);
|
||||||
|
name = TREE_OPERAND (template_id, 0);
|
||||||
|
/* FIXME: What about operators? */
|
||||||
|
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE,
|
||||||
|
20030707);
|
||||||
|
write_source_name (TREE_OPERAND (template_id, 0));
|
||||||
|
write_template_args (TREE_OPERAND (template_id, 1));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* G++ 3.2 incorrectly put out both the "sr" code and
|
/* G++ 3.2 incorrectly put out both the "sr" code and
|
||||||
|
|
359
gcc/cp/parser.c
359
gcc/cp/parser.c
|
@ -1651,6 +1651,8 @@ static tree cp_parser_sizeof_operand
|
||||||
(cp_parser *, enum rid);
|
(cp_parser *, enum rid);
|
||||||
static bool cp_parser_declares_only_class_p
|
static bool cp_parser_declares_only_class_p
|
||||||
(cp_parser *);
|
(cp_parser *);
|
||||||
|
static tree cp_parser_fold_non_dependent_expr
|
||||||
|
(tree);
|
||||||
static bool cp_parser_friend_p
|
static bool cp_parser_friend_p
|
||||||
(tree);
|
(tree);
|
||||||
static cp_token *cp_parser_require
|
static cp_token *cp_parser_require
|
||||||
|
@ -1661,6 +1663,8 @@ static bool cp_parser_token_starts_function_definition_p
|
||||||
(cp_token *);
|
(cp_token *);
|
||||||
static bool cp_parser_next_token_starts_class_definition_p
|
static bool cp_parser_next_token_starts_class_definition_p
|
||||||
(cp_parser *);
|
(cp_parser *);
|
||||||
|
static bool cp_parser_next_token_ends_template_argument_p
|
||||||
|
(cp_parser *);
|
||||||
static enum tag_types cp_parser_token_is_class_key
|
static enum tag_types cp_parser_token_is_class_key
|
||||||
(cp_token *);
|
(cp_token *);
|
||||||
static void cp_parser_check_class_key
|
static void cp_parser_check_class_key
|
||||||
|
@ -2381,7 +2385,6 @@ cp_parser_primary_expression (cp_parser *parser,
|
||||||
cp_parser_error (parser, "expected primary-expression");
|
cp_parser_error (parser, "expected primary-expression");
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
/* Fall through. */
|
|
||||||
|
|
||||||
/* An id-expression can start with either an identifier, a
|
/* An id-expression can start with either an identifier, a
|
||||||
`::' as the beginning of a qualified-id, or the "operator"
|
`::' as the beginning of a qualified-id, or the "operator"
|
||||||
|
@ -2600,30 +2603,7 @@ cp_parser_primary_expression (cp_parser *parser,
|
||||||
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
|
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
|
||||||
{
|
{
|
||||||
tree args = TREE_OPERAND (fns, 1);
|
tree args = TREE_OPERAND (fns, 1);
|
||||||
|
dependent_p = any_dependent_template_arguments_p (args);
|
||||||
if (args && TREE_CODE (args) == TREE_LIST)
|
|
||||||
{
|
|
||||||
while (args)
|
|
||||||
{
|
|
||||||
if (dependent_template_arg_p (TREE_VALUE (args)))
|
|
||||||
{
|
|
||||||
dependent_p = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
args = TREE_CHAIN (args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (args && TREE_CODE (args) == TREE_VEC)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
|
|
||||||
if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
|
|
||||||
{
|
|
||||||
dependent_p = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The functions are those referred to by the
|
/* The functions are those referred to by the
|
||||||
template-id. */
|
template-id. */
|
||||||
fns = TREE_OPERAND (fns, 0);
|
fns = TREE_OPERAND (fns, 0);
|
||||||
|
@ -2687,27 +2667,34 @@ cp_parser_primary_expression (cp_parser *parser,
|
||||||
/* Only certain kinds of names are allowed in constant
|
/* Only certain kinds of names are allowed in constant
|
||||||
expression. Enumerators have already been handled
|
expression. Enumerators have already been handled
|
||||||
above. */
|
above. */
|
||||||
if (parser->constant_expression_p
|
if (parser->constant_expression_p)
|
||||||
|
{
|
||||||
/* Non-type template parameters of integral or
|
/* Non-type template parameters of integral or
|
||||||
enumeration type. */
|
enumeration type are OK. */
|
||||||
&& !(TREE_CODE (decl) == TEMPLATE_PARM_INDEX
|
if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX
|
||||||
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
|
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
|
||||||
|
;
|
||||||
/* Const variables or static data members of integral
|
/* Const variables or static data members of integral
|
||||||
or enumeration types initialized with constant
|
or enumeration types initialized with constant
|
||||||
expressions (or dependent expressions - in this case
|
expressions are OK. We also accept dependent
|
||||||
the check will be done at instantiation time). */
|
initializers; they may turn out to be constant at
|
||||||
&& !(TREE_CODE (decl) == VAR_DECL
|
instantiation-time. */
|
||||||
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
|
else if (TREE_CODE (decl) == VAR_DECL
|
||||||
&& DECL_INITIAL (decl)
|
&& CP_TYPE_CONST_P (TREE_TYPE (decl))
|
||||||
&& (TREE_CONSTANT (DECL_INITIAL (decl))
|
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
|
||||||
|| type_dependent_expression_p
|
&& DECL_INITIAL (decl)
|
||||||
(DECL_INITIAL (decl))
|
&& (TREE_CONSTANT (DECL_INITIAL (decl))
|
||||||
|| value_dependent_expression_p
|
|| type_dependent_expression_p (DECL_INITIAL
|
||||||
(DECL_INITIAL (decl)))))
|
(decl))
|
||||||
{
|
|| value_dependent_expression_p (DECL_INITIAL
|
||||||
if (!parser->allow_non_constant_expression_p)
|
(decl))))
|
||||||
return cp_parser_non_constant_id_expression (decl);
|
;
|
||||||
parser->non_constant_expression_p = true;
|
else
|
||||||
|
{
|
||||||
|
if (!parser->allow_non_constant_expression_p)
|
||||||
|
return cp_parser_non_constant_id_expression (decl);
|
||||||
|
parser->non_constant_expression_p = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser->scope)
|
if (parser->scope)
|
||||||
|
@ -3792,7 +3779,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|
||||||
|| TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
|
|| TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
|
||||||
&& args)
|
&& args)
|
||||||
{
|
{
|
||||||
tree arg;
|
|
||||||
tree identifier = NULL_TREE;
|
tree identifier = NULL_TREE;
|
||||||
tree functions = NULL_TREE;
|
tree functions = NULL_TREE;
|
||||||
|
|
||||||
|
@ -3815,10 +3801,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|
||||||
|
|
||||||
Do Koenig lookup -- unless any of the arguments are
|
Do Koenig lookup -- unless any of the arguments are
|
||||||
type-dependent. */
|
type-dependent. */
|
||||||
for (arg = args; arg; arg = TREE_CHAIN (arg))
|
if (!any_type_dependent_arguments_p (args))
|
||||||
if (type_dependent_expression_p (TREE_VALUE (arg)))
|
|
||||||
break;
|
|
||||||
if (!arg)
|
|
||||||
{
|
{
|
||||||
postfix_expression
|
postfix_expression
|
||||||
= lookup_arg_dependent (identifier, functions, args);
|
= lookup_arg_dependent (identifier, functions, args);
|
||||||
|
@ -3827,14 +3810,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|
||||||
/* The unqualified name could not be resolved. */
|
/* The unqualified name could not be resolved. */
|
||||||
unqualified_name_lookup_error (identifier);
|
unqualified_name_lookup_error (identifier);
|
||||||
postfix_expression = error_mark_node;
|
postfix_expression = error_mark_node;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
postfix_expression
|
|
||||||
= build_call_from_tree (postfix_expression, args,
|
|
||||||
/*diallow_virtual=*/false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
postfix_expression = build_min_nt (LOOKUP_EXPR,
|
else
|
||||||
identifier);
|
postfix_expression = build_min_nt (LOOKUP_EXPR,
|
||||||
|
identifier);
|
||||||
}
|
}
|
||||||
else if (idk == CP_PARSER_ID_KIND_UNQUALIFIED
|
else if (idk == CP_PARSER_ID_KIND_UNQUALIFIED
|
||||||
&& TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
|
&& TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
|
||||||
|
@ -3845,25 +3826,31 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In the body of a template, no further processing is
|
|
||||||
required. */
|
|
||||||
if (processing_template_decl)
|
|
||||||
{
|
|
||||||
postfix_expression = build_nt (CALL_EXPR,
|
|
||||||
postfix_expression,
|
|
||||||
args);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TREE_CODE (postfix_expression) == COMPONENT_REF)
|
if (TREE_CODE (postfix_expression) == COMPONENT_REF)
|
||||||
postfix_expression
|
{
|
||||||
= (build_new_method_call
|
tree instance = TREE_OPERAND (postfix_expression, 0);
|
||||||
(TREE_OPERAND (postfix_expression, 0),
|
tree fn = TREE_OPERAND (postfix_expression, 1);
|
||||||
TREE_OPERAND (postfix_expression, 1),
|
|
||||||
args, NULL_TREE,
|
if (processing_template_decl
|
||||||
(idk == CP_PARSER_ID_KIND_QUALIFIED
|
&& (type_dependent_expression_p (instance)
|
||||||
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
|
|| (!BASELINK_P (fn)
|
||||||
else if (TREE_CODE (postfix_expression) == OFFSET_REF)
|
&& TREE_CODE (fn) != FIELD_DECL)
|
||||||
|
|| any_type_dependent_arguments_p (args)))
|
||||||
|
{
|
||||||
|
postfix_expression
|
||||||
|
= build_min_nt (CALL_EXPR, postfix_expression, args);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
postfix_expression
|
||||||
|
= (build_new_method_call
|
||||||
|
(instance, fn, args, NULL_TREE,
|
||||||
|
(idk == CP_PARSER_ID_KIND_QUALIFIED
|
||||||
|
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
|
||||||
|
}
|
||||||
|
else if (TREE_CODE (postfix_expression) == OFFSET_REF
|
||||||
|
|| TREE_CODE (postfix_expression) == MEMBER_REF
|
||||||
|
|| TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
|
||||||
postfix_expression = (build_offset_ref_call_from_tree
|
postfix_expression = (build_offset_ref_call_from_tree
|
||||||
(postfix_expression, args));
|
(postfix_expression, args));
|
||||||
else if (idk == CP_PARSER_ID_KIND_QUALIFIED)
|
else if (idk == CP_PARSER_ID_KIND_QUALIFIED)
|
||||||
|
@ -3968,7 +3955,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|
||||||
template <typename T> void f(T* t) { t->X::f(); }
|
template <typename T> void f(T* t) { t->X::f(); }
|
||||||
|
|
||||||
Even though "t" is dependent, "X::f" is not and has
|
Even though "t" is dependent, "X::f" is not and has
|
||||||
except that for a BASELINK there is no need to
|
been resolved to a BASELINK; there is no need to
|
||||||
include scope information. */
|
include scope information. */
|
||||||
|
|
||||||
/* But we do need to remember that there was an explicit
|
/* But we do need to remember that there was an explicit
|
||||||
|
@ -4336,7 +4323,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
|
||||||
return build_x_indirect_ref (cast_expression, "unary *");
|
return build_x_indirect_ref (cast_expression, "unary *");
|
||||||
|
|
||||||
case ADDR_EXPR:
|
case ADDR_EXPR:
|
||||||
return build_x_unary_op (ADDR_EXPR, cast_expression);
|
case BIT_NOT_EXPR:
|
||||||
|
return build_x_unary_op (unary_operator, cast_expression);
|
||||||
|
|
||||||
case PREINCREMENT_EXPR:
|
case PREINCREMENT_EXPR:
|
||||||
case PREDECREMENT_EXPR:
|
case PREDECREMENT_EXPR:
|
||||||
|
@ -4354,9 +4342,6 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
|
||||||
case TRUTH_NOT_EXPR:
|
case TRUTH_NOT_EXPR:
|
||||||
return finish_unary_op_expr (unary_operator, cast_expression);
|
return finish_unary_op_expr (unary_operator, cast_expression);
|
||||||
|
|
||||||
case BIT_NOT_EXPR:
|
|
||||||
return build_x_unary_op (BIT_NOT_EXPR, cast_expression);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
@ -5293,7 +5278,6 @@ static tree
|
||||||
cp_parser_expression (cp_parser* parser)
|
cp_parser_expression (cp_parser* parser)
|
||||||
{
|
{
|
||||||
tree expression = NULL_TREE;
|
tree expression = NULL_TREE;
|
||||||
bool saw_comma_p = false;
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -5306,45 +5290,23 @@ cp_parser_expression (cp_parser* parser)
|
||||||
save it away. */
|
save it away. */
|
||||||
if (!expression)
|
if (!expression)
|
||||||
expression = assignment_expression;
|
expression = assignment_expression;
|
||||||
/* Otherwise, chain the expressions together. It is unclear why
|
|
||||||
we do not simply build COMPOUND_EXPRs as we go. */
|
|
||||||
else
|
else
|
||||||
expression = tree_cons (NULL_TREE,
|
expression = build_x_compound_expr (expression,
|
||||||
assignment_expression,
|
assignment_expression);
|
||||||
expression);
|
|
||||||
/* If the next token is not a comma, then we are done with the
|
/* If the next token is not a comma, then we are done with the
|
||||||
expression. */
|
expression. */
|
||||||
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
|
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
|
||||||
break;
|
break;
|
||||||
/* Consume the `,'. */
|
/* Consume the `,'. */
|
||||||
cp_lexer_consume_token (parser->lexer);
|
cp_lexer_consume_token (parser->lexer);
|
||||||
/* The first time we see a `,', we must take special action
|
|
||||||
because the representation used for a single expression is
|
|
||||||
different from that used for a list containing the single
|
|
||||||
expression. */
|
|
||||||
if (!saw_comma_p)
|
|
||||||
{
|
|
||||||
/* Remember that this expression has a `,' in it. */
|
|
||||||
saw_comma_p = true;
|
|
||||||
/* Turn the EXPRESSION into a TREE_LIST so that we can link
|
|
||||||
additional expressions to it. */
|
|
||||||
expression = build_tree_list (NULL_TREE, expression);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build a COMPOUND_EXPR to represent the entire expression, if
|
|
||||||
necessary. We built up the list in reverse order, so we must
|
|
||||||
straighten it out here. */
|
|
||||||
if (saw_comma_p)
|
|
||||||
{
|
|
||||||
/* A comma operator cannot appear in a constant-expression. */
|
/* A comma operator cannot appear in a constant-expression. */
|
||||||
if (parser->constant_expression_p)
|
if (parser->constant_expression_p)
|
||||||
{
|
{
|
||||||
if (!parser->allow_non_constant_expression_p)
|
if (!parser->allow_non_constant_expression_p)
|
||||||
return cp_parser_non_constant_expression ("a comma operator");
|
expression
|
||||||
|
= cp_parser_non_constant_expression ("a comma operator");
|
||||||
parser->non_constant_expression_p = true;
|
parser->non_constant_expression_p = true;
|
||||||
}
|
}
|
||||||
expression = build_x_compound_expr (nreverse (expression));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return expression;
|
return expression;
|
||||||
|
@ -5356,8 +5318,9 @@ cp_parser_expression (cp_parser* parser)
|
||||||
conditional-expression
|
conditional-expression
|
||||||
|
|
||||||
If ALLOW_NON_CONSTANT_P a non-constant expression is silently
|
If ALLOW_NON_CONSTANT_P a non-constant expression is silently
|
||||||
accepted. In that case *NON_CONSTANT_P is set to TRUE. If
|
accepted. If ALLOW_NON_CONSTANT_P is true and the expression is not
|
||||||
ALLOW_NON_CONSTANT_P is false, NON_CONSTANT_P should be NULL. */
|
constant, *NON_CONSTANT_P is set to TRUE. If ALLOW_NON_CONSTANT_P
|
||||||
|
is false, NON_CONSTANT_P should be NULL. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cp_parser_constant_expression (cp_parser* parser,
|
cp_parser_constant_expression (cp_parser* parser,
|
||||||
|
@ -5547,7 +5510,7 @@ cp_parser_labeled_statement (cp_parser* parser)
|
||||||
cp_lexer_consume_token (parser->lexer);
|
cp_lexer_consume_token (parser->lexer);
|
||||||
/* Parse the constant-expression. */
|
/* Parse the constant-expression. */
|
||||||
expr = cp_parser_constant_expression (parser,
|
expr = cp_parser_constant_expression (parser,
|
||||||
/*allow_non_constant=*/false,
|
/*allow_non_constant_p=*/false,
|
||||||
NULL);
|
NULL);
|
||||||
/* Create the label. */
|
/* Create the label. */
|
||||||
statement = finish_case_label (expr, NULL_TREE);
|
statement = finish_case_label (expr, NULL_TREE);
|
||||||
|
@ -8051,13 +8014,21 @@ cp_parser_template_argument_list (cp_parser* parser)
|
||||||
The representation is that of an assignment-expression, type-id, or
|
The representation is that of an assignment-expression, type-id, or
|
||||||
id-expression -- except that the qualified id-expression is
|
id-expression -- except that the qualified id-expression is
|
||||||
evaluated, so that the value returned is either a DECL or an
|
evaluated, so that the value returned is either a DECL or an
|
||||||
OVERLOAD. */
|
OVERLOAD.
|
||||||
|
|
||||||
|
Although the standard says "assignment-expression", it forbids
|
||||||
|
throw-expressions or assignments in the template argument.
|
||||||
|
Therefore, we use "conditional-expression" instead. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cp_parser_template_argument (cp_parser* parser)
|
cp_parser_template_argument (cp_parser* parser)
|
||||||
{
|
{
|
||||||
tree argument;
|
tree argument;
|
||||||
bool template_p;
|
bool template_p;
|
||||||
|
bool address_p;
|
||||||
|
cp_token *token;
|
||||||
|
cp_parser_id_kind idk;
|
||||||
|
tree qualifying_class;
|
||||||
|
|
||||||
/* There's really no way to know what we're looking at, so we just
|
/* There's really no way to know what we're looking at, so we just
|
||||||
try each alternative in order.
|
try each alternative in order.
|
||||||
|
@ -8073,8 +8044,7 @@ cp_parser_template_argument (cp_parser* parser)
|
||||||
argument = cp_parser_type_id (parser);
|
argument = cp_parser_type_id (parser);
|
||||||
/* If the next token isn't a `,' or a `>', then this argument wasn't
|
/* If the next token isn't a `,' or a `>', then this argument wasn't
|
||||||
really finished. */
|
really finished. */
|
||||||
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
|
if (!cp_parser_next_token_ends_template_argument_p (parser))
|
||||||
&& cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER))
|
|
||||||
cp_parser_error (parser, "expected template-argument");
|
cp_parser_error (parser, "expected template-argument");
|
||||||
/* If that worked, we're done. */
|
/* If that worked, we're done. */
|
||||||
if (cp_parser_parse_definitely (parser))
|
if (cp_parser_parse_definitely (parser))
|
||||||
|
@ -8088,8 +8058,7 @@ cp_parser_template_argument (cp_parser* parser)
|
||||||
&template_p);
|
&template_p);
|
||||||
/* If the next token isn't a `,' or a `>', then this argument wasn't
|
/* If the next token isn't a `,' or a `>', then this argument wasn't
|
||||||
really finished. */
|
really finished. */
|
||||||
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
|
if (!cp_parser_next_token_ends_template_argument_p (parser))
|
||||||
&& cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER))
|
|
||||||
cp_parser_error (parser, "expected template-argument");
|
cp_parser_error (parser, "expected template-argument");
|
||||||
if (!cp_parser_error_occurred (parser))
|
if (!cp_parser_error_occurred (parser))
|
||||||
{
|
{
|
||||||
|
@ -8104,8 +8073,101 @@ cp_parser_template_argument (cp_parser* parser)
|
||||||
}
|
}
|
||||||
if (cp_parser_parse_definitely (parser))
|
if (cp_parser_parse_definitely (parser))
|
||||||
return argument;
|
return argument;
|
||||||
/* It must be an assignment-expression. */
|
/* It must be a non-type argument. There permitted cases are given
|
||||||
return cp_parser_assignment_expression (parser);
|
in [temp.arg.nontype]:
|
||||||
|
|
||||||
|
-- an integral constant-expression of integral or enumeration
|
||||||
|
type; or
|
||||||
|
|
||||||
|
-- the name of a non-type template-parameter; or
|
||||||
|
|
||||||
|
-- the name of an object or function with external linkage...
|
||||||
|
|
||||||
|
-- the address of an object or function with external linkage...
|
||||||
|
|
||||||
|
-- a pointer to member... */
|
||||||
|
/* Look for a non-type template parameter. */
|
||||||
|
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
|
||||||
|
{
|
||||||
|
cp_parser_parse_tentatively (parser);
|
||||||
|
argument = cp_parser_primary_expression (parser,
|
||||||
|
&idk,
|
||||||
|
&qualifying_class);
|
||||||
|
if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX
|
||||||
|
|| !cp_parser_next_token_ends_template_argument_p (parser))
|
||||||
|
cp_parser_simulate_error (parser);
|
||||||
|
if (cp_parser_parse_definitely (parser))
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
/* If the next token is "&", the argument must be the address of an
|
||||||
|
object or function with external linkage. */
|
||||||
|
address_p = cp_lexer_next_token_is (parser->lexer, CPP_AND);
|
||||||
|
if (address_p)
|
||||||
|
cp_lexer_consume_token (parser->lexer);
|
||||||
|
/* See if we might have an id-expression. */
|
||||||
|
token = cp_lexer_peek_token (parser->lexer);
|
||||||
|
if (token->type == CPP_NAME
|
||||||
|
|| token->keyword == RID_OPERATOR
|
||||||
|
|| token->type == CPP_SCOPE
|
||||||
|
|| token->type == CPP_TEMPLATE_ID
|
||||||
|
|| token->type == CPP_NESTED_NAME_SPECIFIER)
|
||||||
|
{
|
||||||
|
cp_parser_parse_tentatively (parser);
|
||||||
|
argument = cp_parser_primary_expression (parser,
|
||||||
|
&idk,
|
||||||
|
&qualifying_class);
|
||||||
|
if (cp_parser_error_occurred (parser)
|
||||||
|
|| !cp_parser_next_token_ends_template_argument_p (parser))
|
||||||
|
cp_parser_abort_tentative_parse (parser);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (qualifying_class)
|
||||||
|
argument = finish_qualified_id_expr (qualifying_class,
|
||||||
|
argument,
|
||||||
|
/*done=*/true,
|
||||||
|
address_p);
|
||||||
|
if (TREE_CODE (argument) == VAR_DECL)
|
||||||
|
{
|
||||||
|
/* A variable without external linkage might still be a
|
||||||
|
valid constant-expression, so no error is issued here
|
||||||
|
if the external-linkage check fails. */
|
||||||
|
if (!DECL_EXTERNAL_LINKAGE_P (argument))
|
||||||
|
cp_parser_simulate_error (parser);
|
||||||
|
}
|
||||||
|
else if (is_overloaded_fn (argument))
|
||||||
|
/* All overloaded functions are allowed; if the external
|
||||||
|
linkage test does not pass, an error will be issued
|
||||||
|
later. */
|
||||||
|
;
|
||||||
|
else if (address_p
|
||||||
|
&& (TREE_CODE (argument) == OFFSET_REF
|
||||||
|
|| TREE_CODE (argument) == SCOPE_REF))
|
||||||
|
/* A pointer-to-member. */
|
||||||
|
;
|
||||||
|
else
|
||||||
|
cp_parser_simulate_error (parser);
|
||||||
|
|
||||||
|
if (cp_parser_parse_definitely (parser))
|
||||||
|
{
|
||||||
|
if (address_p)
|
||||||
|
argument = build_x_unary_op (ADDR_EXPR, argument);
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If the argument started with "&", there are no other valid
|
||||||
|
alternatives at this point. */
|
||||||
|
if (address_p)
|
||||||
|
{
|
||||||
|
cp_parser_error (parser, "invalid non-type template argument");
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
/* The argument must be a constant-expression. */
|
||||||
|
argument = cp_parser_constant_expression (parser,
|
||||||
|
/*allow_non_constant_p=*/false,
|
||||||
|
/*non_constant_p=*/NULL);
|
||||||
|
/* If it's non-dependent, simplify it. */
|
||||||
|
return cp_parser_fold_non_dependent_expr (argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse an explicit-instantiation.
|
/* Parse an explicit-instantiation.
|
||||||
|
@ -8914,7 +8976,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
|
||||||
cp_lexer_consume_token (parser->lexer);
|
cp_lexer_consume_token (parser->lexer);
|
||||||
/* Parse the value. */
|
/* Parse the value. */
|
||||||
value = cp_parser_constant_expression (parser,
|
value = cp_parser_constant_expression (parser,
|
||||||
/*allow_non_constant=*/false,
|
/*allow_non_constant_p=*/false,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -9919,29 +9981,8 @@ cp_parser_direct_declarator (cp_parser* parser,
|
||||||
= cp_parser_constant_expression (parser,
|
= cp_parser_constant_expression (parser,
|
||||||
/*allow_non_constant=*/true,
|
/*allow_non_constant=*/true,
|
||||||
&non_constant_p);
|
&non_constant_p);
|
||||||
/* If we're in a template, but the constant-expression
|
if (!non_constant_p)
|
||||||
isn't value dependent, simplify it. We're supposed
|
bounds = cp_parser_fold_non_dependent_expr (bounds);
|
||||||
to treat:
|
|
||||||
|
|
||||||
template <typename T> void f(T[1 + 1]);
|
|
||||||
template <typename T> void f(T[2]);
|
|
||||||
|
|
||||||
as two declarations of the same function, for
|
|
||||||
example. */
|
|
||||||
if (processing_template_decl
|
|
||||||
&& !non_constant_p
|
|
||||||
&& !value_dependent_expression_p (bounds))
|
|
||||||
{
|
|
||||||
HOST_WIDE_INT saved_processing_template_decl;
|
|
||||||
|
|
||||||
saved_processing_template_decl = processing_template_decl;
|
|
||||||
processing_template_decl = 0;
|
|
||||||
bounds = tsubst_copy_and_build (bounds,
|
|
||||||
/*args=*/NULL_TREE,
|
|
||||||
tf_error,
|
|
||||||
/*in_decl=*/NULL_TREE);
|
|
||||||
processing_template_decl = saved_processing_template_decl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
bounds = NULL_TREE;
|
bounds = NULL_TREE;
|
||||||
|
@ -14129,6 +14170,36 @@ cp_parser_declares_only_class_p (cp_parser *parser)
|
||||||
|| cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
|
|| cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Simplify EXPR if it is a non-dependent expression. Returns the
|
||||||
|
(possibly simplified) expression. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
cp_parser_fold_non_dependent_expr (tree expr)
|
||||||
|
{
|
||||||
|
/* If we're in a template, but EXPR isn't value dependent, simplify
|
||||||
|
it. We're supposed to treat:
|
||||||
|
|
||||||
|
template <typename T> void f(T[1 + 1]);
|
||||||
|
template <typename T> void f(T[2]);
|
||||||
|
|
||||||
|
as two declarations of the same function, for example. */
|
||||||
|
if (processing_template_decl
|
||||||
|
&& !type_dependent_expression_p (expr)
|
||||||
|
&& !value_dependent_expression_p (expr))
|
||||||
|
{
|
||||||
|
HOST_WIDE_INT saved_processing_template_decl;
|
||||||
|
|
||||||
|
saved_processing_template_decl = processing_template_decl;
|
||||||
|
processing_template_decl = 0;
|
||||||
|
expr = tsubst_copy_and_build (expr,
|
||||||
|
/*args=*/NULL_TREE,
|
||||||
|
tf_error,
|
||||||
|
/*in_decl=*/NULL_TREE);
|
||||||
|
processing_template_decl = saved_processing_template_decl;
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
|
/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
|
||||||
Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */
|
Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */
|
||||||
|
|
||||||
|
@ -14274,6 +14345,18 @@ cp_parser_next_token_starts_class_definition_p (cp_parser *parser)
|
||||||
return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);
|
return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns TRUE iff the next token is the "," or ">" ending a
|
||||||
|
template-argument. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
|
||||||
|
{
|
||||||
|
cp_token *token;
|
||||||
|
|
||||||
|
token = cp_lexer_peek_token (parser->lexer);
|
||||||
|
return (token->type == CPP_COMMA || token->type == CPP_GREATER);
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns the kind of tag indicated by TOKEN, if it is a class-key,
|
/* Returns the kind of tag indicated by TOKEN, if it is a class-key,
|
||||||
or none_type otherwise. */
|
or none_type otherwise. */
|
||||||
|
|
||||||
|
|
327
gcc/cp/pt.c
327
gcc/cp/pt.c
|
@ -167,7 +167,6 @@ static void copy_default_args_to_explicit_spec (tree);
|
||||||
static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
|
static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
|
||||||
static int eq_local_specializations (const void *, const void *);
|
static int eq_local_specializations (const void *, const void *);
|
||||||
static bool dependent_type_p_r (tree);
|
static bool dependent_type_p_r (tree);
|
||||||
static bool dependent_template_id_p (tree, tree);
|
|
||||||
static tree tsubst (tree, tree, tsubst_flags_t, tree);
|
static tree tsubst (tree, tree, tsubst_flags_t, tree);
|
||||||
static tree tsubst_expr (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 (tree, tree, tsubst_flags_t, tree);
|
||||||
|
@ -3594,9 +3593,6 @@ convert_template_argument (tree parm,
|
||||||
if (invalid_nontype_parm_type_p (t, complain))
|
if (invalid_nontype_parm_type_p (t, complain))
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (processing_template_decl)
|
|
||||||
arg = maybe_fold_nontype_arg (arg);
|
|
||||||
|
|
||||||
if (!uses_template_parms (arg) && !uses_template_parms (t))
|
if (!uses_template_parms (arg) && !uses_template_parms (t))
|
||||||
/* We used to call digest_init here. However, digest_init
|
/* We used to call digest_init here. However, digest_init
|
||||||
will report errors, which we don't want when complain
|
will report errors, which we don't want when complain
|
||||||
|
@ -7108,9 +7104,8 @@ tsubst_baselink (tree baselink, tree object_type,
|
||||||
template_id_p = true;
|
template_id_p = true;
|
||||||
template_args = TREE_OPERAND (fns, 1);
|
template_args = TREE_OPERAND (fns, 1);
|
||||||
fns = TREE_OPERAND (fns, 0);
|
fns = TREE_OPERAND (fns, 0);
|
||||||
template_args = tsubst_copy (template_args, args,
|
template_args = tsubst_copy_and_build (template_args, args,
|
||||||
complain, in_decl);
|
complain, in_decl);
|
||||||
maybe_fold_nontype_args (template_args);
|
|
||||||
}
|
}
|
||||||
name = DECL_NAME (get_first_fn (fns));
|
name = DECL_NAME (get_first_fn (fns));
|
||||||
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
|
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
|
||||||
|
@ -8003,30 +7998,17 @@ tsubst_copy_and_build (tree t,
|
||||||
|
|
||||||
case PREDECREMENT_EXPR:
|
case PREDECREMENT_EXPR:
|
||||||
case PREINCREMENT_EXPR:
|
case PREINCREMENT_EXPR:
|
||||||
if (TREE_TYPE (t))
|
|
||||||
return tsubst_copy (t, args, complain, in_decl);
|
|
||||||
else
|
|
||||||
return build_x_unary_op
|
|
||||||
(TREE_CODE (t),
|
|
||||||
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
|
|
||||||
in_decl));
|
|
||||||
|
|
||||||
case NEGATE_EXPR:
|
case NEGATE_EXPR:
|
||||||
case BIT_NOT_EXPR:
|
case BIT_NOT_EXPR:
|
||||||
if (TREE_TYPE (t))
|
|
||||||
return tsubst_copy (t, args, complain, in_decl);
|
|
||||||
else
|
|
||||||
return build_x_unary_op
|
|
||||||
(TREE_CODE (t),
|
|
||||||
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
|
|
||||||
in_decl));
|
|
||||||
|
|
||||||
case ABS_EXPR:
|
case ABS_EXPR:
|
||||||
if (TREE_TYPE (t))
|
case TRUTH_NOT_EXPR:
|
||||||
return t;
|
case CONVERT_EXPR: /* Unary + */
|
||||||
return build_x_unary_op
|
case REALPART_EXPR:
|
||||||
(TREE_CODE (t),
|
case IMAGPART_EXPR:
|
||||||
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
|
return (build_x_unary_op
|
||||||
|
(TREE_CODE (t),
|
||||||
|
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
|
||||||
|
in_decl)));
|
||||||
|
|
||||||
case ADDR_EXPR:
|
case ADDR_EXPR:
|
||||||
op1 = TREE_OPERAND (t, 0);
|
op1 = TREE_OPERAND (t, 0);
|
||||||
|
@ -8037,18 +8019,6 @@ tsubst_copy_and_build (tree t,
|
||||||
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
|
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
|
||||||
return build_x_unary_op (ADDR_EXPR, op1);
|
return build_x_unary_op (ADDR_EXPR, op1);
|
||||||
|
|
||||||
case TRUTH_NOT_EXPR:
|
|
||||||
case CONVERT_EXPR: /* Unary + */
|
|
||||||
case REALPART_EXPR:
|
|
||||||
case IMAGPART_EXPR:
|
|
||||||
if (TREE_TYPE (t))
|
|
||||||
return tsubst_copy (t, args, complain, in_decl);
|
|
||||||
else
|
|
||||||
return build_x_unary_op
|
|
||||||
(TREE_CODE (t),
|
|
||||||
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
|
|
||||||
in_decl));
|
|
||||||
|
|
||||||
case PLUS_EXPR:
|
case PLUS_EXPR:
|
||||||
case MINUS_EXPR:
|
case MINUS_EXPR:
|
||||||
case MULT_EXPR:
|
case MULT_EXPR:
|
||||||
|
@ -8119,15 +8089,25 @@ tsubst_copy_and_build (tree t,
|
||||||
|
|
||||||
case SIZEOF_EXPR:
|
case SIZEOF_EXPR:
|
||||||
case ALIGNOF_EXPR:
|
case ALIGNOF_EXPR:
|
||||||
{
|
op1 = TREE_OPERAND (t, 0);
|
||||||
tree r =
|
if (!args)
|
||||||
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl);
|
{
|
||||||
if (!TYPE_P (r))
|
/* When there are no ARGS, we are trying to evaluate a
|
||||||
return TREE_CODE (t) == SIZEOF_EXPR ?
|
non-dependent expression from the parser. Trying to do
|
||||||
expr_sizeof (r) : c_alignof_expr (r);
|
the substitutions may not work. */
|
||||||
else
|
if (!TYPE_P (op1))
|
||||||
return cxx_sizeof_or_alignof_type (r, TREE_CODE (t), true);
|
op1 = TREE_TYPE (op1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++skip_evaluation;
|
||||||
|
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
|
||||||
|
--skip_evaluation;
|
||||||
|
}
|
||||||
|
if (TREE_CODE (t) == SIZEOF_EXPR)
|
||||||
|
return finish_sizeof (op1);
|
||||||
|
else
|
||||||
|
return finish_alignof (op1);
|
||||||
|
|
||||||
case MODOP_EXPR:
|
case MODOP_EXPR:
|
||||||
return build_x_modify_expr
|
return build_x_modify_expr
|
||||||
|
@ -8162,15 +8142,11 @@ tsubst_copy_and_build (tree t,
|
||||||
DELETE_EXPR_USE_GLOBAL (t));
|
DELETE_EXPR_USE_GLOBAL (t));
|
||||||
|
|
||||||
case COMPOUND_EXPR:
|
case COMPOUND_EXPR:
|
||||||
{
|
return (build_x_compound_expr
|
||||||
if (tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl)
|
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
|
||||||
== NULL_TREE)
|
in_decl),
|
||||||
return build_x_compound_expr
|
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
|
||||||
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
|
in_decl)));
|
||||||
in_decl));
|
|
||||||
else
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
case CALL_EXPR:
|
case CALL_EXPR:
|
||||||
{
|
{
|
||||||
|
@ -8210,25 +8186,23 @@ tsubst_copy_and_build (tree t,
|
||||||
complain, in_decl);
|
complain, in_decl);
|
||||||
|
|
||||||
if (BASELINK_P (function))
|
if (BASELINK_P (function))
|
||||||
return build_call_from_tree (function, call_args, 1);
|
qualified_p = 1;
|
||||||
else
|
|
||||||
{
|
|
||||||
if (call_args != NULL_TREE && koenig_name)
|
|
||||||
function = lookup_arg_dependent (koenig_name,
|
|
||||||
function,
|
|
||||||
call_args);
|
|
||||||
|
|
||||||
if (TREE_CODE (function) == OFFSET_REF)
|
if (call_args != NULL_TREE && koenig_name)
|
||||||
return build_offset_ref_call_from_tree (function, call_args);
|
function = lookup_arg_dependent (koenig_name,
|
||||||
if (TREE_CODE (function) == COMPONENT_REF)
|
function,
|
||||||
return (build_new_method_call
|
call_args);
|
||||||
(TREE_OPERAND (function, 0),
|
|
||||||
TREE_OPERAND (function, 1),
|
if (TREE_CODE (function) == OFFSET_REF)
|
||||||
call_args, NULL_TREE,
|
return build_offset_ref_call_from_tree (function, call_args);
|
||||||
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
|
if (TREE_CODE (function) == COMPONENT_REF)
|
||||||
return finish_call_expr (function, call_args,
|
return (build_new_method_call
|
||||||
/*disallow_virtual=*/qualified_p);
|
(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 COND_EXPR:
|
case COND_EXPR:
|
||||||
|
@ -8389,6 +8363,11 @@ tsubst_copy_and_build (tree t,
|
||||||
case VAR_DECL:
|
case VAR_DECL:
|
||||||
if (args)
|
if (args)
|
||||||
t = tsubst_copy (t, args, complain, in_decl);
|
t = tsubst_copy (t, args, complain, in_decl);
|
||||||
|
else
|
||||||
|
/* If there are no ARGS, then we are evaluating a
|
||||||
|
non-dependent expression. If the expression is
|
||||||
|
non-dependent, the variable must be a constant. */
|
||||||
|
t = DECL_INITIAL (t);
|
||||||
return convert_from_reference (t);
|
return convert_from_reference (t);
|
||||||
|
|
||||||
case VA_ARG_EXPR:
|
case VA_ARG_EXPR:
|
||||||
|
@ -11491,26 +11470,46 @@ value_dependent_expression_p (tree expression)
|
||||||
with an expression that is value-dependent. */
|
with an expression that is value-dependent. */
|
||||||
if (TREE_CODE (expression) == VAR_DECL
|
if (TREE_CODE (expression) == VAR_DECL
|
||||||
&& DECL_INITIAL (expression)
|
&& DECL_INITIAL (expression)
|
||||||
&& INTEGRAL_OR_ENUMERATION_TYPE_P (expression)
|
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (expression))
|
||||||
&& value_dependent_expression_p (DECL_INITIAL (expression)))
|
&& value_dependent_expression_p (DECL_INITIAL (expression)))
|
||||||
return true;
|
return true;
|
||||||
/* These expressions are value-dependent if the type to which the
|
/* These expressions are value-dependent if the type to which the
|
||||||
cast occurs is dependent or the expression being casted is
|
cast occurs is dependent or the expression being casted is
|
||||||
value-dependent. */
|
value-dependent. */
|
||||||
if ((TREE_CODE (expression) == DYNAMIC_CAST_EXPR
|
if (TREE_CODE (expression) == DYNAMIC_CAST_EXPR
|
||||||
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|
||||||
|| TREE_CODE (expression) == CONST_CAST_EXPR
|
|| TREE_CODE (expression) == CONST_CAST_EXPR
|
||||||
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|
||||||
|| TREE_CODE (expression) == CAST_EXPR)
|
|| TREE_CODE (expression) == CAST_EXPR)
|
||||||
&& (dependent_type_p (TREE_TYPE (expression))
|
{
|
||||||
|| value_dependent_expression_p (TREE_OPERAND (expression, 0))))
|
if (dependent_type_p (TREE_TYPE (expression)))
|
||||||
return true;
|
return true;
|
||||||
/* A `sizeof' expression where the sizeof operand is a type is
|
/* A functional cast has a list of operands. */
|
||||||
value-dependent if the type is dependent. If the type was not
|
expression = TREE_OPERAND (expression, 0);
|
||||||
dependent, we would no longer have a SIZEOF_EXPR, so any
|
if (TREE_CODE (expression) == TREE_LIST)
|
||||||
SIZEOF_EXPR is dependent. */
|
{
|
||||||
if (TREE_CODE (expression) == SIZEOF_EXPR)
|
do
|
||||||
return true;
|
{
|
||||||
|
if (value_dependent_expression_p (TREE_VALUE (expression)))
|
||||||
|
return true;
|
||||||
|
expression = TREE_CHAIN (expression);
|
||||||
|
}
|
||||||
|
while (expression);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return value_dependent_expression_p (expression);
|
||||||
|
}
|
||||||
|
/* A `sizeof' expression is value-dependent if the operand is
|
||||||
|
type-dependent. */
|
||||||
|
if (TREE_CODE (expression) == SIZEOF_EXPR
|
||||||
|
|| TREE_CODE (expression) == ALIGNOF_EXPR)
|
||||||
|
{
|
||||||
|
expression = TREE_OPERAND (expression, 0);
|
||||||
|
if (TYPE_P (expression))
|
||||||
|
return dependent_type_p (expression);
|
||||||
|
return type_dependent_expression_p (expression);
|
||||||
|
}
|
||||||
/* A constant expression is value-dependent if any subexpression is
|
/* A constant expression is value-dependent if any subexpression is
|
||||||
value-dependent. */
|
value-dependent. */
|
||||||
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
|
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
|
||||||
|
@ -11574,10 +11573,11 @@ type_dependent_expression_p (tree expression)
|
||||||
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|
||||||
|| TREE_CODE (expression) == CAST_EXPR)
|
|| TREE_CODE (expression) == CAST_EXPR)
|
||||||
return dependent_type_p (TREE_TYPE (expression));
|
return dependent_type_p (TREE_TYPE (expression));
|
||||||
|
|
||||||
/* The types of these expressions depends only on the type created
|
/* The types of these expressions depends only on the type created
|
||||||
by the expression. */
|
by the expression. */
|
||||||
else if (TREE_CODE (expression) == NEW_EXPR
|
if (TREE_CODE (expression) == NEW_EXPR
|
||||||
|| TREE_CODE (expression) == VEC_NEW_EXPR)
|
|| TREE_CODE (expression) == VEC_NEW_EXPR)
|
||||||
{
|
{
|
||||||
/* For NEW_EXPR tree nodes created inside a template, either
|
/* For NEW_EXPR tree nodes created inside a template, either
|
||||||
the object type itself or a TREE_LIST may appear as the
|
the object type itself or a TREE_LIST may appear as the
|
||||||
|
@ -11601,12 +11601,53 @@ type_dependent_expression_p (tree expression)
|
||||||
INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
|
INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (TREE_TYPE (expression) == unknown_type_node)
|
||||||
|
{
|
||||||
|
if (TREE_CODE (expression) == ADDR_EXPR)
|
||||||
|
return type_dependent_expression_p (TREE_OPERAND (expression, 0));
|
||||||
|
if (TREE_CODE (expression) == BASELINK)
|
||||||
|
expression = BASELINK_FUNCTIONS (expression);
|
||||||
|
if (TREE_CODE (expression) == TEMPLATE_ID_EXPR)
|
||||||
|
{
|
||||||
|
if (any_dependent_template_arguments_p (TREE_OPERAND (expression,
|
||||||
|
1)))
|
||||||
|
return true;
|
||||||
|
expression = TREE_OPERAND (expression, 0);
|
||||||
|
}
|
||||||
|
if (TREE_CODE (expression) == OVERLOAD)
|
||||||
|
{
|
||||||
|
while (expression)
|
||||||
|
{
|
||||||
|
if (type_dependent_expression_p (OVL_CURRENT (expression)))
|
||||||
|
return true;
|
||||||
|
expression = OVL_NEXT (expression);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
return (dependent_type_p (TREE_TYPE (expression)));
|
return (dependent_type_p (TREE_TYPE (expression)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns TRUE if ARGS (a TREE_LIST of arguments to a function call)
|
||||||
|
contains a type-dependent expression. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
any_type_dependent_arguments_p (tree args)
|
||||||
|
{
|
||||||
|
while (args)
|
||||||
|
{
|
||||||
|
if (type_dependent_expression_p (TREE_VALUE (args)))
|
||||||
|
return true;
|
||||||
|
args = TREE_CHAIN (args);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns TRUE if the ARG (a template argument) is dependent. */
|
/* Returns TRUE if the ARG (a template argument) is dependent. */
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
dependent_template_arg_p (tree arg)
|
dependent_template_arg_p (tree arg)
|
||||||
{
|
{
|
||||||
if (!processing_template_decl)
|
if (!processing_template_decl)
|
||||||
|
@ -11622,18 +11663,36 @@ dependent_template_arg_p (tree arg)
|
||||||
|| value_dependent_expression_p (arg));
|
|| value_dependent_expression_p (arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns TRUE if the specialization TMPL<ARGS> is dependent. */
|
/* Returns true if ARGS (a collection of template arguments) contains
|
||||||
|
any dependent arguments. */
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
dependent_template_id_p (tree tmpl, tree args)
|
any_dependent_template_arguments_p (tree args)
|
||||||
{
|
{
|
||||||
int i;
|
if (!args)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
my_friendly_assert (TREE_CODE (args) == TREE_LIST
|
||||||
|
|| TREE_CODE (args) == TREE_VEC,
|
||||||
|
20030707);
|
||||||
|
|
||||||
|
if (TREE_CODE (args) == TREE_LIST)
|
||||||
|
{
|
||||||
|
while (args)
|
||||||
|
{
|
||||||
|
if (dependent_template_arg_p (TREE_VALUE (args)))
|
||||||
|
return true;
|
||||||
|
args = TREE_CHAIN (args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
|
||||||
|
if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (dependent_template_p (tmpl))
|
|
||||||
return true;
|
|
||||||
for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
|
|
||||||
if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
|
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11646,12 +11705,24 @@ dependent_template_p (tree tmpl)
|
||||||
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
|
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
|
||||||
|| TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
|
|| TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
|
||||||
return true;
|
return true;
|
||||||
|
/* So are qualified names that have not been looked up. */
|
||||||
|
if (TREE_CODE (tmpl) == SCOPE_REF)
|
||||||
|
return true;
|
||||||
/* So are member templates of dependent classes. */
|
/* So are member templates of dependent classes. */
|
||||||
if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
|
if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
|
||||||
return dependent_type_p (DECL_CONTEXT (tmpl));
|
return dependent_type_p (DECL_CONTEXT (tmpl));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns TRUE if the specialization TMPL<ARGS> is dependent. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
dependent_template_id_p (tree tmpl, tree args)
|
||||||
|
{
|
||||||
|
return (dependent_template_p (tmpl)
|
||||||
|
|| any_dependent_template_arguments_p (args));
|
||||||
|
}
|
||||||
|
|
||||||
/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
|
/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
|
||||||
TYPENAME_TYPE corresponds. Returns ERROR_MARK_NODE if no such TYPE
|
TYPENAME_TYPE corresponds. Returns ERROR_MARK_NODE if no such TYPE
|
||||||
can be found. Note that this function peers inside uninstantiated
|
can be found. Note that this function peers inside uninstantiated
|
||||||
|
@ -11730,4 +11801,54 @@ resolve_typename_type (tree type, bool only_current_p)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* EXPR is an expression which is not type-dependent. Return a proxy
|
||||||
|
for EXPR that can be used to compute the types of larger
|
||||||
|
expressions containing EXPR. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
build_non_dependent_expr (tree expr)
|
||||||
|
{
|
||||||
|
/* Preserve null pointer constants so that the type of things like
|
||||||
|
"p == 0" where "p" is a pointer can be determined. */
|
||||||
|
if (null_ptr_cst_p (expr))
|
||||||
|
return expr;
|
||||||
|
/* Preserve OVERLOADs; the functions must be available to resolve
|
||||||
|
types. */
|
||||||
|
if (TREE_CODE (expr) == OVERLOAD)
|
||||||
|
return expr;
|
||||||
|
/* Otherwise, build a NON_DEPENDENT_EXPR.
|
||||||
|
|
||||||
|
REFERENCE_TYPEs are not stripped for expressions in templates
|
||||||
|
because doing so would play havoc with mangling. Consider, for
|
||||||
|
example:
|
||||||
|
|
||||||
|
template <typename T> void f<T& g>() { g(); }
|
||||||
|
|
||||||
|
In the body of "f", the expression for "g" will have
|
||||||
|
REFERENCE_TYPE, even though the standard says that it should
|
||||||
|
not. The reason is that we must preserve the syntactic form of
|
||||||
|
the expression so that mangling (say) "f<g>" inside the body of
|
||||||
|
"f" works out correctly. Therefore, the REFERENCE_TYPE is
|
||||||
|
stripped here. */
|
||||||
|
return build (NON_DEPENDENT_EXPR, non_reference (TREE_TYPE (expr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ARGS is a TREE_LIST of expressions as arguments to a function call.
|
||||||
|
Return a new TREE_LIST with the various arguments replaced with
|
||||||
|
equivalent non-dependent expressions. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
build_non_dependent_args (tree args)
|
||||||
|
{
|
||||||
|
tree a;
|
||||||
|
tree new_args;
|
||||||
|
|
||||||
|
new_args = NULL_TREE;
|
||||||
|
for (a = args; a; a = TREE_CHAIN (a))
|
||||||
|
new_args = tree_cons (NULL_TREE,
|
||||||
|
build_non_dependent_expr (TREE_VALUE (a)),
|
||||||
|
new_args);
|
||||||
|
return nreverse (new_args);
|
||||||
|
}
|
||||||
|
|
||||||
#include "gt-cp-pt.h"
|
#include "gt-cp-pt.h"
|
||||||
|
|
|
@ -1449,8 +1449,12 @@ finish_stmt_expr (tree rtl_expr)
|
||||||
tree result;
|
tree result;
|
||||||
|
|
||||||
/* If the last thing in the statement-expression was not an
|
/* If the last thing in the statement-expression was not an
|
||||||
expression-statement, then it has type `void'. */
|
expression-statement, then it has type `void'. In a template, we
|
||||||
if (!last_expr_type)
|
cannot distinguish the case where the last expression-statement
|
||||||
|
had a dependent type from the case where the last statement was
|
||||||
|
not an expression-statement. Therefore, we (incorrectly) treat
|
||||||
|
the STMT_EXPR as dependent in that case. */
|
||||||
|
if (!last_expr_type && !processing_template_decl)
|
||||||
last_expr_type = void_type_node;
|
last_expr_type = void_type_node;
|
||||||
result = build_min (STMT_EXPR, last_expr_type, last_tree);
|
result = build_min (STMT_EXPR, last_expr_type, last_tree);
|
||||||
TREE_SIDE_EFFECTS (result) = 1;
|
TREE_SIDE_EFFECTS (result) = 1;
|
||||||
|
@ -1482,16 +1486,32 @@ finish_stmt_expr (tree rtl_expr)
|
||||||
tree
|
tree
|
||||||
finish_call_expr (tree fn, tree args, bool disallow_virtual)
|
finish_call_expr (tree fn, tree args, bool disallow_virtual)
|
||||||
{
|
{
|
||||||
|
tree result;
|
||||||
|
tree orig_fn;
|
||||||
|
tree orig_args;
|
||||||
|
|
||||||
if (fn == error_mark_node || args == error_mark_node)
|
if (fn == error_mark_node || args == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (processing_template_decl)
|
|
||||||
return build_nt (CALL_EXPR, fn, args, NULL_TREE);
|
|
||||||
|
|
||||||
/* ARGS should be a list of arguments. */
|
/* ARGS should be a list of arguments. */
|
||||||
my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
|
my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
|
||||||
20020712);
|
20020712);
|
||||||
|
|
||||||
|
orig_fn = fn;
|
||||||
|
orig_args = args;
|
||||||
|
|
||||||
|
if (processing_template_decl)
|
||||||
|
{
|
||||||
|
if (type_dependent_expression_p (fn)
|
||||||
|
|| any_type_dependent_arguments_p (args))
|
||||||
|
return build_nt (CALL_EXPR, fn, args);
|
||||||
|
if (!BASELINK_P (fn)
|
||||||
|
&& TREE_CODE (fn) != PSEUDO_DTOR_EXPR
|
||||||
|
&& TREE_TYPE (fn) != unknown_type_node)
|
||||||
|
fn = build_non_dependent_expr (fn);
|
||||||
|
args = build_non_dependent_args (orig_args);
|
||||||
|
}
|
||||||
|
|
||||||
/* A reference to a member function will appear as an overloaded
|
/* A reference to a member function will appear as an overloaded
|
||||||
function (rather than a BASELINK) if an unqualified name was used
|
function (rather than a BASELINK) if an unqualified name was used
|
||||||
to refer to it. */
|
to refer to it. */
|
||||||
|
@ -1512,6 +1532,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = NULL_TREE;
|
||||||
if (BASELINK_P (fn))
|
if (BASELINK_P (fn))
|
||||||
{
|
{
|
||||||
tree object;
|
tree object;
|
||||||
|
@ -1551,17 +1572,22 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
|
||||||
object = build_dummy_object (DECL_CONTEXT (representative_fn));
|
object = build_dummy_object (DECL_CONTEXT (representative_fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
return build_new_method_call (object, fn, args, NULL_TREE,
|
if (processing_template_decl)
|
||||||
(disallow_virtual
|
{
|
||||||
? LOOKUP_NONVIRTUAL : 0));
|
if (type_dependent_expression_p (object))
|
||||||
|
return build_nt (CALL_EXPR, orig_fn, orig_args);
|
||||||
|
object = build_non_dependent_expr (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = build_new_method_call (object, fn, args, NULL_TREE,
|
||||||
|
(disallow_virtual
|
||||||
|
? LOOKUP_NONVIRTUAL : 0));
|
||||||
}
|
}
|
||||||
else if (is_overloaded_fn (fn))
|
else if (is_overloaded_fn (fn))
|
||||||
/* A call to a namespace-scope function. */
|
/* A call to a namespace-scope function. */
|
||||||
return build_new_function_call (fn, args);
|
result = build_new_function_call (fn, args);
|
||||||
else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
|
else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
|
||||||
{
|
{
|
||||||
tree result;
|
|
||||||
|
|
||||||
if (args)
|
if (args)
|
||||||
error ("arguments to destructor are not allowed");
|
error ("arguments to destructor are not allowed");
|
||||||
/* Mark the pseudo-destructor call as having side-effects so
|
/* Mark the pseudo-destructor call as having side-effects so
|
||||||
|
@ -1570,20 +1596,18 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
|
||||||
void_type_node,
|
void_type_node,
|
||||||
TREE_OPERAND (fn, 0));
|
TREE_OPERAND (fn, 0));
|
||||||
TREE_SIDE_EFFECTS (result) = 1;
|
TREE_SIDE_EFFECTS (result) = 1;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
else if (CLASS_TYPE_P (TREE_TYPE (fn)))
|
else if (CLASS_TYPE_P (TREE_TYPE (fn)))
|
||||||
{
|
/* If the "function" is really an object of class type, it might
|
||||||
/* If the "function" is really an object of class type, it might
|
have an overloaded `operator ()'. */
|
||||||
have an overloaded `operator ()'. */
|
result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
|
||||||
tree result;
|
if (!result)
|
||||||
result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
|
/* A call where the function is unknown. */
|
||||||
if (result)
|
result = build_function_call (fn, args);
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A call where the function is unknown. */
|
if (processing_template_decl)
|
||||||
return build_function_call (fn, args);
|
return build (CALL_EXPR, TREE_TYPE (result), orig_fn, orig_args);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finish a call to a postfix increment or decrement or EXPR. (Which
|
/* Finish a call to a postfix increment or decrement or EXPR. (Which
|
||||||
|
|
|
@ -174,6 +174,14 @@ lvalue_p_1 (tree ref,
|
||||||
return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
|
return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
|
||||||
? clk_none : clk_ordinary);
|
? clk_none : clk_ordinary);
|
||||||
|
|
||||||
|
case NON_DEPENDENT_EXPR:
|
||||||
|
/* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
|
||||||
|
things like "&E" where "E" is an expression with a
|
||||||
|
non-dependent type work. It is safe to be lenient because an
|
||||||
|
error will be issued when the template is instantiated if "E"
|
||||||
|
is not an lvalue. */
|
||||||
|
return clk_ordinary;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
424
gcc/cp/typeck.c
424
gcc/cp/typeck.c
|
@ -1417,7 +1417,7 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
|
||||||
|
|
||||||
my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
|
my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (op, type);
|
return build_min (op, size_type_node, type);
|
||||||
|
|
||||||
op_name = operator_name_info[(int) op].name;
|
op_name = operator_name_info[(int) op].name;
|
||||||
|
|
||||||
|
@ -1446,7 +1446,7 @@ tree
|
||||||
expr_sizeof (tree e)
|
expr_sizeof (tree e)
|
||||||
{
|
{
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (SIZEOF_EXPR, e);
|
return build_min (SIZEOF_EXPR, size_type_node, e);
|
||||||
|
|
||||||
if (TREE_CODE (e) == COMPONENT_REF
|
if (TREE_CODE (e) == COMPONENT_REF
|
||||||
&& DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
|
&& DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
|
||||||
|
@ -2015,17 +2015,36 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
|
||||||
tree
|
tree
|
||||||
finish_class_member_access_expr (tree object, tree name)
|
finish_class_member_access_expr (tree object, tree name)
|
||||||
{
|
{
|
||||||
|
tree expr;
|
||||||
tree object_type;
|
tree object_type;
|
||||||
tree member;
|
tree member;
|
||||||
tree access_path = NULL_TREE;
|
tree access_path = NULL_TREE;
|
||||||
|
tree orig_object = object;
|
||||||
|
tree orig_name = name;
|
||||||
|
|
||||||
if (object == error_mark_node || name == error_mark_node)
|
if (object == error_mark_node || name == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (processing_template_decl)
|
|
||||||
return build_min_nt (COMPONENT_REF, object, name);
|
|
||||||
|
|
||||||
object_type = TREE_TYPE (object);
|
object_type = TREE_TYPE (object);
|
||||||
|
|
||||||
|
if (processing_template_decl)
|
||||||
|
{
|
||||||
|
if (/* If OBJECT_TYPE is dependent, so is OBJECT.NAME. */
|
||||||
|
dependent_type_p (object_type)
|
||||||
|
/* If NAME is "f<args>", where either 'f' or 'args' is
|
||||||
|
dependent, then the expression is dependent. */
|
||||||
|
|| (TREE_CODE (name) == TEMPLATE_ID_EXPR
|
||||||
|
&& dependent_template_id_p (TREE_OPERAND (name, 0),
|
||||||
|
TREE_OPERAND (name, 1)))
|
||||||
|
/* If NAME is "T::X" where "T" is dependent, then the
|
||||||
|
expression is dependent. */
|
||||||
|
|| (TREE_CODE (name) == SCOPE_REF
|
||||||
|
&& TYPE_P (TREE_OPERAND (name, 0))
|
||||||
|
&& dependent_type_p (TREE_OPERAND (name, 0))))
|
||||||
|
return build_min_nt (COMPONENT_REF, object, name);
|
||||||
|
object = build_non_dependent_expr (object);
|
||||||
|
}
|
||||||
|
|
||||||
if (TREE_CODE (object_type) == REFERENCE_TYPE)
|
if (TREE_CODE (object_type) == REFERENCE_TYPE)
|
||||||
{
|
{
|
||||||
object = convert_from_reference (object);
|
object = convert_from_reference (object);
|
||||||
|
@ -2057,6 +2076,7 @@ finish_class_member_access_expr (tree object, tree name)
|
||||||
{
|
{
|
||||||
bool is_template_id = false;
|
bool is_template_id = false;
|
||||||
tree template_args = NULL_TREE;
|
tree template_args = NULL_TREE;
|
||||||
|
tree scope;
|
||||||
|
|
||||||
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
||||||
{
|
{
|
||||||
|
@ -2067,8 +2087,6 @@ finish_class_member_access_expr (tree object, tree name)
|
||||||
|
|
||||||
if (TREE_CODE (name) == SCOPE_REF)
|
if (TREE_CODE (name) == SCOPE_REF)
|
||||||
{
|
{
|
||||||
tree scope;
|
|
||||||
|
|
||||||
/* A qualified name. The qualifying class or namespace `S' has
|
/* A qualified name. The qualifying class or namespace `S' has
|
||||||
already been looked up; it is either a TYPE or a
|
already been looked up; it is either a TYPE or a
|
||||||
NAMESPACE_DECL. The member name is either an IDENTIFIER_NODE
|
NAMESPACE_DECL. The member name is either an IDENTIFIER_NODE
|
||||||
|
@ -2095,57 +2113,35 @@ finish_class_member_access_expr (tree object, tree name)
|
||||||
access_path = lookup_base (object_type, scope, ba_check, NULL);
|
access_path = lookup_base (object_type, scope, ba_check, NULL);
|
||||||
if (!access_path || access_path == error_mark_node)
|
if (!access_path || access_path == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (TREE_CODE (name) == BIT_NOT_EXPR)
|
|
||||||
member = lookup_destructor (object, scope, name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Look up the member. */
|
|
||||||
member = lookup_member (access_path, name, /*protect=*/1,
|
|
||||||
/*want_type=*/false);
|
|
||||||
if (member == NULL_TREE)
|
|
||||||
{
|
|
||||||
error ("'%D' has no member named '%E'", object_type, name);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
if (member == error_mark_node)
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (name) == BIT_NOT_EXPR)
|
else
|
||||||
member = lookup_destructor (object, /*scope=*/NULL_TREE, name);
|
|
||||||
else if (TREE_CODE (name) == IDENTIFIER_NODE)
|
|
||||||
{
|
{
|
||||||
/* An unqualified name. */
|
scope = NULL_TREE;
|
||||||
member = lookup_member (object_type, name, /*protect=*/1,
|
access_path = object_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TREE_CODE (name) == BIT_NOT_EXPR)
|
||||||
|
member = lookup_destructor (object, scope, name);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Look up the member. */
|
||||||
|
member = lookup_member (access_path, name, /*protect=*/1,
|
||||||
/*want_type=*/false);
|
/*want_type=*/false);
|
||||||
if (member == NULL_TREE)
|
if (member == NULL_TREE)
|
||||||
{
|
{
|
||||||
error ("'%D' has no member named '%E'", object_type, name);
|
error ("'%D' has no member named '%E'", object_type, name);
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else if (member == error_mark_node)
|
if (member == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The YACC parser sometimes gives us things that are not names.
|
|
||||||
These always indicate errors. The recursive-descent parser
|
|
||||||
does not do this, so this code can go away once that parser
|
|
||||||
replaces the YACC parser. */
|
|
||||||
error ("invalid use of `%D'", name);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_template_id)
|
if (is_template_id)
|
||||||
{
|
{
|
||||||
tree template = member;
|
tree template = member;
|
||||||
|
|
||||||
if (BASELINK_P (template))
|
if (BASELINK_P (template))
|
||||||
BASELINK_FUNCTIONS (template)
|
template = lookup_template_function (template, template_args);
|
||||||
= build_nt (TEMPLATE_ID_EXPR,
|
|
||||||
BASELINK_FUNCTIONS (template),
|
|
||||||
template_args);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error ("`%D' is not a member template function", name);
|
error ("`%D' is not a member template function", name);
|
||||||
|
@ -2157,8 +2153,12 @@ finish_class_member_access_expr (tree object, tree name)
|
||||||
if (TREE_DEPRECATED (member))
|
if (TREE_DEPRECATED (member))
|
||||||
warn_deprecated_use (member);
|
warn_deprecated_use (member);
|
||||||
|
|
||||||
return build_class_member_access_expr (object, member, access_path,
|
expr = build_class_member_access_expr (object, member, access_path,
|
||||||
/*preserve_reference=*/false);
|
/*preserve_reference=*/false);
|
||||||
|
if (processing_template_decl && expr != error_mark_node)
|
||||||
|
return build_min (COMPONENT_REF, TREE_TYPE (expr), orig_object,
|
||||||
|
orig_name);
|
||||||
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return an expression for the MEMBER_NAME field in the internal
|
/* Return an expression for the MEMBER_NAME field in the internal
|
||||||
|
@ -2196,18 +2196,27 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
|
||||||
Must also handle REFERENCE_TYPEs for C++. */
|
Must also handle REFERENCE_TYPEs for C++. */
|
||||||
|
|
||||||
tree
|
tree
|
||||||
build_x_indirect_ref (tree ptr, const char *errorstring)
|
build_x_indirect_ref (tree expr, const char *errorstring)
|
||||||
{
|
{
|
||||||
|
tree orig_expr = expr;
|
||||||
tree rval;
|
tree rval;
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (INDIRECT_REF, ptr);
|
{
|
||||||
|
if (type_dependent_expression_p (expr))
|
||||||
|
return build_min_nt (INDIRECT_REF, expr);
|
||||||
|
expr = build_non_dependent_expr (expr);
|
||||||
|
}
|
||||||
|
|
||||||
rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
|
rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE,
|
||||||
NULL_TREE);
|
NULL_TREE);
|
||||||
if (rval)
|
if (!rval)
|
||||||
|
rval = build_indirect_ref (expr, errorstring);
|
||||||
|
|
||||||
|
if (processing_template_decl && rval != error_mark_node)
|
||||||
|
return build_min (INDIRECT_REF, TREE_TYPE (rval), orig_expr);
|
||||||
|
else
|
||||||
return rval;
|
return rval;
|
||||||
return build_indirect_ref (ptr, errorstring);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tree
|
tree
|
||||||
|
@ -2826,191 +2835,32 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
|
||||||
tree
|
tree
|
||||||
build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
|
build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
|
||||||
{
|
{
|
||||||
|
tree orig_arg1;
|
||||||
|
tree orig_arg2;
|
||||||
|
tree expr;
|
||||||
|
|
||||||
|
orig_arg1 = arg1;
|
||||||
|
orig_arg2 = arg2;
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (code, arg1, arg2);
|
|
||||||
|
|
||||||
if (code == DOTSTAR_EXPR)
|
|
||||||
return build_m_component_ref (arg1, arg2);
|
|
||||||
|
|
||||||
return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
tree
|
|
||||||
build_template_expr (enum tree_code code, tree op0, tree op1, tree op2)
|
|
||||||
{
|
|
||||||
tree type;
|
|
||||||
|
|
||||||
/* If any of the operands is erroneous the result is erroneous too. */
|
|
||||||
if (error_operand_p (op0)
|
|
||||||
|| (op1 && error_operand_p (op1))
|
|
||||||
|| (op2 && error_operand_p (op2)))
|
|
||||||
return error_mark_node;
|
|
||||||
|
|
||||||
if (dependent_type_p (TREE_TYPE (op0))
|
|
||||||
|| (op1 && dependent_type_p (TREE_TYPE (op1)))
|
|
||||||
|| (op2 && dependent_type_p (TREE_TYPE (op2))))
|
|
||||||
/* If at least one operand has a dependent type, we cannot
|
|
||||||
determine the type of the expression until instantiation time. */
|
|
||||||
type = NULL_TREE;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
struct z_candidate *cand;
|
if (type_dependent_expression_p (arg1)
|
||||||
tree op0_type;
|
|| type_dependent_expression_p (arg2))
|
||||||
tree op1_type;
|
return build_min_nt (code, arg1, arg2);
|
||||||
tree op2_type;
|
arg1 = build_non_dependent_expr (arg1);
|
||||||
|
arg2 = build_non_dependent_expr (arg2);
|
||||||
/* None of the operands is dependent, so we can compute the type
|
|
||||||
of the expression at this point. We must compute the type so
|
|
||||||
that in things like:
|
|
||||||
|
|
||||||
template <int I>
|
|
||||||
void f() { S<sizeof(I + 3)> s; ... }
|
|
||||||
|
|
||||||
we can tell that the type of "s" is non-dependent.
|
|
||||||
|
|
||||||
If we're processing a template argument, we do not want to
|
|
||||||
actually change the operands in any way. Adding conversions,
|
|
||||||
performing constant folding, etc., would all change mangled
|
|
||||||
names. For example, in:
|
|
||||||
|
|
||||||
template <int I>
|
|
||||||
void f(S<sizeof(3 + 4 + I)>);
|
|
||||||
|
|
||||||
we need to determine that "3 + 4 + I" has type "int", without
|
|
||||||
actually turning the expression into "7 + I". */
|
|
||||||
cand = find_overloaded_op (code, op0, op1, op2);
|
|
||||||
if (cand)
|
|
||||||
/* If an overloaded operator was found, the expression will
|
|
||||||
have the type returned by the function. */
|
|
||||||
type = non_reference (TREE_TYPE (cand->fn));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* There is no overloaded operator so we can just use the
|
|
||||||
default rules for determining the type of the operand. */
|
|
||||||
op0_type = TREE_TYPE (op0);
|
|
||||||
op1_type = op1 ? TREE_TYPE (op1) : NULL_TREE;
|
|
||||||
op2_type = op2 ? TREE_TYPE (op2) : NULL_TREE;
|
|
||||||
type = NULL_TREE;
|
|
||||||
|
|
||||||
switch (code)
|
|
||||||
{
|
|
||||||
case MODIFY_EXPR:
|
|
||||||
/* [expr.ass]
|
|
||||||
|
|
||||||
The result of the assignment operation is the value
|
|
||||||
stored in the left operand. */
|
|
||||||
type = op0_type;
|
|
||||||
break;
|
|
||||||
case COMPONENT_REF:
|
|
||||||
/* Implement this case. */
|
|
||||||
break;
|
|
||||||
case POSTINCREMENT_EXPR:
|
|
||||||
case POSTDECREMENT_EXPR:
|
|
||||||
/* [expr.post.incr]
|
|
||||||
|
|
||||||
The type of the result is the cv-unqualified version
|
|
||||||
of the type of the operand. */
|
|
||||||
type = TYPE_MAIN_VARIANT (op0_type);
|
|
||||||
break;
|
|
||||||
case PREINCREMENT_EXPR:
|
|
||||||
case PREDECREMENT_EXPR:
|
|
||||||
/* [expr.pre.incr]
|
|
||||||
|
|
||||||
The value is the new value of the operand. */
|
|
||||||
type = op0_type;
|
|
||||||
break;
|
|
||||||
case INDIRECT_REF:
|
|
||||||
/* [expr.unary.op]
|
|
||||||
|
|
||||||
If the type of the expression is "pointer to T", the
|
|
||||||
type of the result is "T". */
|
|
||||||
type = TREE_TYPE (op0_type);
|
|
||||||
break;
|
|
||||||
case ADDR_EXPR:
|
|
||||||
/* [expr.unary.op]
|
|
||||||
|
|
||||||
If the type of the expression is "T", the type of the
|
|
||||||
result is "pointer to T". */
|
|
||||||
/* FIXME: Handle the pointer-to-member case. */
|
|
||||||
break;
|
|
||||||
case MEMBER_REF:
|
|
||||||
/* FIXME: Implement this case. */
|
|
||||||
break;
|
|
||||||
case LSHIFT_EXPR:
|
|
||||||
case RSHIFT_EXPR:
|
|
||||||
/* [expr.shift]
|
|
||||||
|
|
||||||
The type of the result is that of the promoted left
|
|
||||||
operand. */
|
|
||||||
break;
|
|
||||||
case PLUS_EXPR:
|
|
||||||
case MINUS_EXPR:
|
|
||||||
/* FIXME: Be careful of special pointer-arithmetic
|
|
||||||
cases. */
|
|
||||||
/* Fall through. */
|
|
||||||
case MAX_EXPR:
|
|
||||||
case MIN_EXPR:
|
|
||||||
/* These are GNU extensions; the result type is computed
|
|
||||||
as it would be for other arithmetic operators. */
|
|
||||||
/* Fall through. */
|
|
||||||
case BIT_AND_EXPR:
|
|
||||||
case BIT_XOR_EXPR:
|
|
||||||
case BIT_IOR_EXPR:
|
|
||||||
case MULT_EXPR:
|
|
||||||
case TRUNC_DIV_EXPR:
|
|
||||||
case TRUNC_MOD_EXPR:
|
|
||||||
/* [expr.bit.and], [expr.xor], [expr.or], [expr.mul]
|
|
||||||
|
|
||||||
The usual arithmetic conversions are performed on the
|
|
||||||
operands and determine the type of the result. */
|
|
||||||
/* FIXME: Check that this is possible. */
|
|
||||||
type = type_after_usual_arithmetic_conversions (t1, t2);
|
|
||||||
break;
|
|
||||||
case GT_EXPR:
|
|
||||||
case LT_EXPR:
|
|
||||||
case GE_EXPR:
|
|
||||||
case LE_EXPR:
|
|
||||||
case EQ_EXPR:
|
|
||||||
case NE_EXPR:
|
|
||||||
/* [expr.rel]
|
|
||||||
|
|
||||||
The type of the result is bool. */
|
|
||||||
type = boolean_type_node;
|
|
||||||
break;
|
|
||||||
case TRUTH_ANDIF_EXPR:
|
|
||||||
case TRUTH_ORIF_EXPR:
|
|
||||||
/* [expr.log.and], [expr.log.org]
|
|
||||||
|
|
||||||
The result is a bool. */
|
|
||||||
type = boolean_type_node;
|
|
||||||
break;
|
|
||||||
case COND_EXPR:
|
|
||||||
/* FIXME: Handle special rules for conditional
|
|
||||||
expressions. */
|
|
||||||
break;
|
|
||||||
case COMPOUND_EXPR:
|
|
||||||
type = op1_type;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
/* If the type of the expression could not be determined,
|
|
||||||
something is wrong. */
|
|
||||||
if (!type)
|
|
||||||
abort ();
|
|
||||||
/* If the type is erroneous, the expression is erroneous
|
|
||||||
too. */
|
|
||||||
if (type == error_mark_node)
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return build_min (code, type, op0, op1, op2, NULL_TREE);
|
if (code == DOTSTAR_EXPR)
|
||||||
}
|
expr = build_m_component_ref (arg1, arg2);
|
||||||
|
else
|
||||||
|
expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
|
||||||
|
|
||||||
#endif
|
if (processing_template_decl && expr != error_mark_node)
|
||||||
|
return build_min (code, TREE_TYPE (expr), orig_arg1, orig_arg2);
|
||||||
|
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Build a binary-operation expression without default conversions.
|
/* Build a binary-operation expression without default conversions.
|
||||||
CODE is the kind of expression to build.
|
CODE is the kind of expression to build.
|
||||||
|
@ -3839,11 +3689,18 @@ pointer_diff (register tree op0, register tree op1, register tree ptrtype)
|
||||||
tree
|
tree
|
||||||
build_x_unary_op (enum tree_code code, tree xarg)
|
build_x_unary_op (enum tree_code code, tree xarg)
|
||||||
{
|
{
|
||||||
|
tree orig_expr = xarg;
|
||||||
tree exp;
|
tree exp;
|
||||||
int ptrmem = 0;
|
int ptrmem = 0;
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (code, xarg, NULL_TREE);
|
{
|
||||||
|
if (type_dependent_expression_p (xarg))
|
||||||
|
return build_min_nt (code, xarg, NULL_TREE);
|
||||||
|
xarg = build_non_dependent_expr (xarg);
|
||||||
|
}
|
||||||
|
|
||||||
|
exp = NULL_TREE;
|
||||||
|
|
||||||
/* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
|
/* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
|
||||||
error message. */
|
error message. */
|
||||||
|
@ -3854,15 +3711,8 @@ build_x_unary_op (enum tree_code code, tree xarg)
|
||||||
|| (TREE_CODE (xarg) == OFFSET_REF)))
|
|| (TREE_CODE (xarg) == OFFSET_REF)))
|
||||||
/* don't look for a function */;
|
/* don't look for a function */;
|
||||||
else
|
else
|
||||||
{
|
exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE);
|
||||||
tree rval;
|
if (!exp && code == ADDR_EXPR)
|
||||||
|
|
||||||
rval = build_new_op (code, LOOKUP_NORMAL, xarg,
|
|
||||||
NULL_TREE, NULL_TREE);
|
|
||||||
if (rval || code != ADDR_EXPR)
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
if (code == ADDR_EXPR)
|
|
||||||
{
|
{
|
||||||
/* A pointer to member-function can be formed only by saying
|
/* A pointer to member-function can be formed only by saying
|
||||||
&X::mf. */
|
&X::mf. */
|
||||||
|
@ -3897,15 +3747,16 @@ build_x_unary_op (enum tree_code code, tree xarg)
|
||||||
ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE));
|
ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE));
|
||||||
PTRMEM_OK_P (xarg) = ptrmem;
|
PTRMEM_OK_P (xarg) = ptrmem;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (xarg) == TARGET_EXPR)
|
else if (TREE_CODE (xarg) == TARGET_EXPR)
|
||||||
warning ("taking address of temporary");
|
warning ("taking address of temporary");
|
||||||
|
exp = build_unary_op (ADDR_EXPR, xarg, 0);
|
||||||
|
if (TREE_CODE (exp) == ADDR_EXPR)
|
||||||
|
PTRMEM_OK_P (exp) = ptrmem;
|
||||||
}
|
}
|
||||||
exp = build_unary_op (code, xarg, 0);
|
|
||||||
if (TREE_CODE (exp) == ADDR_EXPR)
|
|
||||||
PTRMEM_OK_P (exp) = ptrmem;
|
|
||||||
|
|
||||||
|
if (processing_template_decl && exp != error_mark_node)
|
||||||
|
return build_min (code, TREE_TYPE (exp), orig_expr);
|
||||||
return exp;
|
return exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4631,53 +4482,76 @@ cxx_mark_addressable (tree exp)
|
||||||
tree
|
tree
|
||||||
build_x_conditional_expr (tree ifexp, tree op1, tree op2)
|
build_x_conditional_expr (tree ifexp, tree op1, tree op2)
|
||||||
{
|
{
|
||||||
if (processing_template_decl)
|
tree orig_ifexp = ifexp;
|
||||||
return build_min_nt (COND_EXPR, ifexp, op1, op2);
|
tree orig_op1 = op1;
|
||||||
|
tree orig_op2 = op2;
|
||||||
|
tree expr;
|
||||||
|
|
||||||
return build_conditional_expr (ifexp, op1, op2);
|
if (processing_template_decl)
|
||||||
|
{
|
||||||
|
/* The standard says that the expression is type-dependent if
|
||||||
|
IFEXP is type-dependent, even though the eventual type of the
|
||||||
|
expression doesn't dependent on IFEXP. */
|
||||||
|
if (type_dependent_expression_p (ifexp)
|
||||||
|
|| type_dependent_expression_p (op1)
|
||||||
|
|| type_dependent_expression_p (op2))
|
||||||
|
return build_min_nt (COND_EXPR, ifexp, op1, op2);
|
||||||
|
ifexp = build_non_dependent_expr (ifexp);
|
||||||
|
op1 = build_non_dependent_expr (op1);
|
||||||
|
op2 = build_non_dependent_expr (op2);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr = build_conditional_expr (ifexp, op1, op2);
|
||||||
|
if (processing_template_decl && expr != error_mark_node)
|
||||||
|
return build_min (COND_EXPR, TREE_TYPE (expr),
|
||||||
|
orig_ifexp, orig_op1, orig_op2);
|
||||||
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle overloading of the ',' operator when needed. Otherwise,
|
/* Handle overloading of the ',' operator when needed. Otherwise,
|
||||||
this function just builds an expression list. */
|
this function just builds an expression list. */
|
||||||
|
|
||||||
tree
|
tree
|
||||||
build_x_compound_expr (tree list)
|
build_x_compound_expr (tree op1, tree op2)
|
||||||
{
|
{
|
||||||
tree rest = TREE_CHAIN (list);
|
|
||||||
tree result;
|
tree result;
|
||||||
|
tree orig_op1 = op1;
|
||||||
|
tree orig_op2 = op2;
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (COMPOUND_EXPR, list, NULL_TREE);
|
|
||||||
|
|
||||||
if (rest == NULL_TREE)
|
|
||||||
return build_compound_expr (list);
|
|
||||||
|
|
||||||
result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL,
|
|
||||||
TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
|
|
||||||
if (result)
|
|
||||||
return build_x_compound_expr (tree_cons (NULL_TREE, result,
|
|
||||||
TREE_CHAIN (rest)));
|
|
||||||
|
|
||||||
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
|
|
||||||
{
|
{
|
||||||
/* FIXME: This test should be in the implicit cast to void of the LHS. */
|
if (type_dependent_expression_p (op1)
|
||||||
/* the left-hand operand of a comma expression is like an expression
|
|| type_dependent_expression_p (op2))
|
||||||
statement: we should warn if it doesn't have any side-effects,
|
return build_min_nt (COMPOUND_EXPR, op1, op2);
|
||||||
unless it was explicitly cast to (void). */
|
op1 = build_non_dependent_expr (op1);
|
||||||
if (warn_unused_value
|
op2 = build_non_dependent_expr (op2);
|
||||||
&& !(TREE_CODE (TREE_VALUE(list)) == CONVERT_EXPR
|
|
||||||
&& VOID_TYPE_P (TREE_TYPE (TREE_VALUE(list)))))
|
|
||||||
warning("left-hand operand of comma expression has no effect");
|
|
||||||
}
|
}
|
||||||
#if 0 /* this requires a gcc backend patch to export warn_if_unused_value */
|
|
||||||
else if (warn_unused_value)
|
|
||||||
warn_if_unused_value (TREE_VALUE(list));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return build_compound_expr
|
result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE);
|
||||||
(tree_cons (NULL_TREE, TREE_VALUE (list),
|
if (!result)
|
||||||
build_tree_list (NULL_TREE,
|
{
|
||||||
build_x_compound_expr (rest))));
|
if (! TREE_SIDE_EFFECTS (op1))
|
||||||
|
{
|
||||||
|
/* FIXME: This test should be in the implicit cast to void
|
||||||
|
of the LHS. */
|
||||||
|
/* the left-hand operand of a comma expression is like an expression
|
||||||
|
statement: we should warn if it doesn't have any side-effects,
|
||||||
|
unless it was explicitly cast to (void). */
|
||||||
|
if (warn_unused_value
|
||||||
|
&& !(TREE_CODE (op1) == CONVERT_EXPR
|
||||||
|
&& VOID_TYPE_P (TREE_TYPE (op1))))
|
||||||
|
warning("left-hand operand of comma expression has no effect");
|
||||||
|
}
|
||||||
|
result = build_compound_expr (tree_cons (NULL_TREE,
|
||||||
|
op1,
|
||||||
|
build_tree_list (NULL_TREE,
|
||||||
|
op2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processing_template_decl && result != error_mark_node)
|
||||||
|
return build_min (COMPOUND_EXPR, TREE_TYPE (result),
|
||||||
|
orig_op1, orig_op2);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a list of expressions, return a compound expression
|
/* Given a list of expressions, return a compound expression
|
||||||
|
|
|
@ -980,44 +980,48 @@ build_scoped_ref (tree datum, tree basetype, tree* binfo_p)
|
||||||
delegation is detected. */
|
delegation is detected. */
|
||||||
|
|
||||||
tree
|
tree
|
||||||
build_x_arrow (tree datum)
|
build_x_arrow (tree expr)
|
||||||
{
|
{
|
||||||
|
tree orig_expr = expr;
|
||||||
tree types_memoized = NULL_TREE;
|
tree types_memoized = NULL_TREE;
|
||||||
register tree rval = datum;
|
tree type = TREE_TYPE (expr);
|
||||||
tree type = TREE_TYPE (rval);
|
|
||||||
tree last_rval = NULL_TREE;
|
tree last_rval = NULL_TREE;
|
||||||
|
|
||||||
if (type == error_mark_node)
|
if (type == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (ARROW_EXPR, rval);
|
{
|
||||||
|
if (type_dependent_expression_p (expr))
|
||||||
|
return build_min_nt (ARROW_EXPR, expr);
|
||||||
|
expr = build_non_dependent_expr (expr);
|
||||||
|
}
|
||||||
|
|
||||||
if (TREE_CODE (type) == REFERENCE_TYPE)
|
if (TREE_CODE (type) == REFERENCE_TYPE)
|
||||||
{
|
{
|
||||||
rval = convert_from_reference (rval);
|
expr = convert_from_reference (expr);
|
||||||
type = TREE_TYPE (rval);
|
type = TREE_TYPE (expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_AGGR_TYPE (type))
|
if (IS_AGGR_TYPE (type))
|
||||||
{
|
{
|
||||||
while ((rval = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, rval,
|
while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr,
|
||||||
NULL_TREE, NULL_TREE)))
|
NULL_TREE, NULL_TREE)))
|
||||||
{
|
{
|
||||||
if (rval == error_mark_node)
|
if (expr == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (value_member (TREE_TYPE (rval), types_memoized))
|
if (value_member (TREE_TYPE (expr), types_memoized))
|
||||||
{
|
{
|
||||||
error ("circular pointer delegation detected");
|
error ("circular pointer delegation detected");
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
types_memoized = tree_cons (NULL_TREE, TREE_TYPE (rval),
|
types_memoized = tree_cons (NULL_TREE, TREE_TYPE (expr),
|
||||||
types_memoized);
|
types_memoized);
|
||||||
}
|
}
|
||||||
last_rval = rval;
|
last_rval = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_rval == NULL_TREE)
|
if (last_rval == NULL_TREE)
|
||||||
|
@ -1030,10 +1034,17 @@ build_x_arrow (tree datum)
|
||||||
last_rval = convert_from_reference (last_rval);
|
last_rval = convert_from_reference (last_rval);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
last_rval = decay_conversion (rval);
|
last_rval = decay_conversion (expr);
|
||||||
|
|
||||||
if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
|
if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
|
||||||
return build_indirect_ref (last_rval, NULL);
|
{
|
||||||
|
if (processing_template_decl)
|
||||||
|
return build_min (ARROW_EXPR,
|
||||||
|
TREE_TYPE (TREE_TYPE (last_rval)),
|
||||||
|
orig_expr);
|
||||||
|
|
||||||
|
return build_indirect_ref (last_rval, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (types_memoized)
|
if (types_memoized)
|
||||||
error ("result of `operator->()' yields non-pointer result");
|
error ("result of `operator->()' yields non-pointer result");
|
||||||
|
|
|
@ -2908,7 +2908,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
|
||||||
|
|
||||||
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
|
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
|
||||||
{
|
{
|
||||||
arg0 = TREE_OPERAND (exp, 0);
|
if (first_rtl_op (code) > 0)
|
||||||
|
arg0 = TREE_OPERAND (exp, 0);
|
||||||
if (TREE_CODE_CLASS (code) == '<'
|
if (TREE_CODE_CLASS (code) == '<'
|
||||||
|| TREE_CODE_CLASS (code) == '1'
|
|| TREE_CODE_CLASS (code) == '1'
|
||||||
|| TREE_CODE_CLASS (code) == '2')
|
|| TREE_CODE_CLASS (code) == '2')
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
2003-07-08 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
* g++.dg/abi/mangle17.C: Make sure template expressions are
|
||||||
|
dependent.
|
||||||
|
* g++.dg/abi/mangle4.C: Mark erroneous casts.
|
||||||
|
* g++.dg/debug/debug7.C: Mark erronous new-declarator.
|
||||||
|
* g++.dg/opt/stack1.C: Remove erroneous code.
|
||||||
|
* g++.dg/parse/template7.C: New test.
|
||||||
|
* g++.dg/template/dependent-expr1.C: Mark erroneous code.
|
||||||
|
* g++.old-deja/g++.pt/crash4.C: Likewise.
|
||||||
|
|
||||||
2003-07-09 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
2003-07-09 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||||
|
|
||||||
* gcc.dg/const-elim-1.c (dg-final): Change regexp to match labels
|
* gcc.dg/const-elim-1.c (dg-final): Change regexp to match labels
|
||||||
|
|
|
@ -4,8 +4,8 @@ enum E { e = 3 };
|
||||||
|
|
||||||
template <int I> struct S {};
|
template <int I> struct S {};
|
||||||
|
|
||||||
template <int I> void f (S<e + int (3.7)>) {}
|
template <int I> void f (S<I + e + int (3.7)>) {}
|
||||||
template void f<7>(S<e + int (3.7)>); // { dg-warning "mangle" }
|
template void f<7>(S<7 + e + int (3.7)>); // { dg-warning "mangle" }
|
||||||
|
|
||||||
template <int I> void g (S<e + int (3.7)>) {}
|
template <int I> void g (S<I + e + int (3.7)>) {}
|
||||||
template void g<7>(S<e + int (3.7)>); // { dg-warning "mangle" }
|
template void g<7>(S<7 + e + int (3.7)>); // { dg-warning "mangle" }
|
||||||
|
|
|
@ -8,19 +8,17 @@ template<const A* a> class C {};
|
||||||
template<const B* b> class D {};
|
template<const B* b> class D {};
|
||||||
template<B* b> class E {};
|
template<B* b> class E {};
|
||||||
|
|
||||||
template<const B* b> void f(D<b> &, C<static_cast<const A*>(b)> &) {}
|
template<const B* b> void f(D<b> &, C<static_cast<const A*>(b)> &) {} // { dg-error "" }
|
||||||
template<const B* b> void g(D<b> &, E<const_cast<B*>(b)> &) {}
|
template<const B* b> void g(D<b> &, E<const_cast<B*>(b)> &) {} // { dg-error "" }
|
||||||
|
|
||||||
B b;
|
B b;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
C<static_cast<const A*>(&b)> c;
|
C<static_cast<const A*>(&b)> c; // { dg-error "" }
|
||||||
D<&b> d;
|
D<&b> d;
|
||||||
E<const_cast<B*>(&b)> e;
|
E<const_cast<B*>(&b)> e; // { dg-error "" }
|
||||||
f(d, c);
|
f(d, c); // { dg-error "" }
|
||||||
g(d, e);
|
g(d, e); // { dg-error "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
// { dg-final { scan-assembler "\n_?_Z1fIXadL_Z1bEEEvR1DIXT_EER1CIXcvPK1AT_EE\[: \t\n\]" } }
|
|
||||||
// { dg-final { scan-assembler "\n_?_Z1gIXadL_Z1bEEEvR1DIXT_EER1EIXcvP1BT_EE\[: \t\n\]" } }
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ main() {
|
||||||
|
|
||||||
int a = 4;
|
int a = 4;
|
||||||
int b = 5;
|
int b = 5;
|
||||||
int (*x)[b] = new int[a][b];
|
int (*x)[b] = new int[a][b]; // { dg-error "" }
|
||||||
|
|
||||||
x[2][1] = 7;
|
x[2][1] = 7;
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ template<typename=void>
|
||||||
struct adaptor {
|
struct adaptor {
|
||||||
adaptor (matrix<> &m) : m(&m), upper_ (1) {}
|
adaptor (matrix<> &m) : m(&m), upper_ (1) {}
|
||||||
|
|
||||||
int size1 () const { return m->size1 (); }
|
int size1 () const;
|
||||||
int size2 () const { return 3; }
|
int size2 () const { return 3; }
|
||||||
int lower () const { return 1; }
|
int lower () const { return 1; }
|
||||||
int upper () const { return upper_; }
|
int upper () const { return upper_; }
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
template <int I>
|
||||||
|
void f();
|
||||||
|
|
||||||
|
void g() { f<(3, 2)>(); } // { dg-error "" }
|
|
@ -21,9 +21,9 @@ namespace std
|
||||||
Foo (__alignof__ (x));
|
Foo (__alignof__ (x));
|
||||||
Foo (x->~I ());
|
Foo (x->~I ());
|
||||||
// Foo (typeid (I));
|
// Foo (typeid (I));
|
||||||
Foo (delete x);
|
Foo (delete x); // { dg-error "" }
|
||||||
Foo (delete[] x);
|
Foo (delete[] x); // { dg-error "" }
|
||||||
Foo (throw x);
|
Foo (throw x); // { dg-error "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// { dg-do assemble }
|
// { dg-do compile }
|
||||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
template <int> struct S1{};
|
template <int> struct S1{};
|
||||||
|
@ -7,5 +7,5 @@ struct S2 { int i; };
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void f(S2 s2) {
|
void f(S2 s2) {
|
||||||
S1<s2.i> s1;
|
S1<s2.i> s1; // { dg-error "" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
2003-07-09 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
* gcj/array.h (JvPrimClass): Don't parenthesize the output.
|
||||||
|
|
||||||
2003-07-09 Michael Koch <konqueror@gmx.de>
|
2003-07-09 Michael Koch <konqueror@gmx.de>
|
||||||
|
|
||||||
* gnu/java/awt/peer/gtk/GtkComponentPeer.java,
|
* gnu/java/awt/peer/gtk/GtkComponentPeer.java,
|
||||||
|
|
|
@ -71,7 +71,9 @@ typedef JArray<jstring> *jstringArray;
|
||||||
extern java::lang::Class _Jv_byteClass, _Jv_shortClass, _Jv_intClass,
|
extern java::lang::Class _Jv_byteClass, _Jv_shortClass, _Jv_intClass,
|
||||||
_Jv_longClass, _Jv_booleanClass, _Jv_charClass, _Jv_floatClass,
|
_Jv_longClass, _Jv_booleanClass, _Jv_charClass, _Jv_floatClass,
|
||||||
_Jv_doubleClass, _Jv_voidClass;
|
_Jv_doubleClass, _Jv_voidClass;
|
||||||
#define JvPrimClass(TYPE) (& _Jv_##TYPE##Class)
|
/* The definition of this macro cannot be enclosed in parentheses
|
||||||
|
because "JvPrimClass(x)" is used as a template argument. */
|
||||||
|
#define JvPrimClass(TYPE) & _Jv_##TYPE##Class
|
||||||
|
|
||||||
extern "C" jobjectArray _Jv_NewObjectArray(jsize length, jclass, jobject init);
|
extern "C" jobjectArray _Jv_NewObjectArray(jsize length, jclass, jobject init);
|
||||||
extern "C" jobject _Jv_NewPrimArray (jclass eltype, jint count);
|
extern "C" jobject _Jv_NewPrimArray (jclass eltype, jint count);
|
||||||
|
|
Loading…
Reference in New Issue