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:
Mark Mitchell 2003-07-09 08:48:08 +00:00 committed by Mark Mitchell
parent 844c00ed16
commit d17811fd1a
26 changed files with 945 additions and 840 deletions

View File

@ -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>
* toplev.c (warn_dummy, W_options): Die.

View File

@ -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>
* 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_new_method_call): Likewise.
* 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.
(ocp_convert): Do not call resolve_offset_ref.
(convert_to_void): Likewise.
(build_expr_type_conversion): Likewise.
(delete_sanity): Likewise.
(resolve_offset_ref): Simplify greatly.
* decl2.c (delete_sanity): Likewise.
* init.c (resolve_offset_ref): Simplify greatly.
(build_vec_delete): Do not call resolve_offset_ref.
* parser.c (cp_parser_postfix_expression): Call resolve_offset_ref
if appropriate.

View File

@ -325,8 +325,7 @@ build_call (tree function, tree parms)
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
information to get protected accesses correct. This parameter is used
by build_member_call.
information to get protected accesses correct.
FLAGS is the logical disjunction of zero or more LOOKUP_
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;
int template_only = 0;
bool any_viable_p;
tree orig_instance;
tree orig_fns;
tree orig_args;
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)
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. */
user_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);
}
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;
}

View File

@ -238,6 +238,16 @@ DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", 'e', 2)
DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
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
setup_vtbl_pointer (and appears in all functions, not just ctors). */
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 1)

View File

@ -215,6 +215,7 @@ struct diagnostic_context;
#define abi_version_at_least(N) \
(flag_abi_version == 0 || flag_abi_version >= (N))
/* Language-dependent contents of an identifier. */
@ -3775,7 +3776,6 @@ extern void import_export_tinfo (tree, tree, bool);
extern void finish_file (void);
extern tree build_cleanup (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 tree current_decl_namespace (void);
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_type_value (tree);
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 resolve_offset_ref (tree);
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 int processing_template_parmlist;
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_id_p (tree, tree);
extern bool type_dependent_expression_p (tree);
extern bool any_type_dependent_arguments_p (tree);
extern bool value_dependent_expression_p (tree);
extern tree resolve_typename_type (tree, bool);
extern tree template_for_substitution (tree);
extern tree build_non_dependent_expr (tree);
extern tree build_non_dependent_args (tree);
/* in repo.c */
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 unary_complex_lvalue (enum tree_code, 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_static_cast (tree, tree);
extern tree build_reinterpret_cast (tree, tree);

View File

@ -398,59 +398,77 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
tree
grok_array_decl (tree array_expr, tree index_exp)
{
tree type = TREE_TYPE (array_expr);
tree p1, p2, i1, i2;
tree type;
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;
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);
type = non_reference (type);
/* If they have an `operator[]', use that. */
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);
/* 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;
tree p1, p2, i1, i2;
/* 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 (array_expr == error_mark_node || index_exp == error_mark_node)
error ("ambiguous conversion for array subscript");
return build_array_ref (array_expr, index_exp);
if (processing_template_decl && expr != error_mark_node)
return build_min (ARRAY_REF, TREE_TYPE (expr), orig_array_expr,
orig_index_exp);
return expr;
}
/* 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)
{
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
represented as an OFFSET_REF:
@ -2958,79 +3005,18 @@ build_offset_ref_call_from_tree (tree fn, tree args)
struct B { void g(); };
void (B::*p)();
void B::g() { (this->*p)(); } */
if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL)
/* This case should now be handled elsewhere. */
abort ();
else
if (TREE_CODE (fn) == OFFSET_REF)
{
object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0);
fn = TREE_OPERAND (fn, 1);
fn = get_member_function_from_ptrfunc (&object_addr, fn);
args = tree_cons (NULL_TREE, object_addr, args);
}
return build_function_call (fn, args);
}
/* FN indicates the function to call. Name resolution has been
performed on FN. ARGS are the arguments to the function. They
have already been semantically analyzed. DISALLOW_VIRTUAL is true
if the function call should be determined at compile time, even if
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);
expr = build_function_call (fn, args);
if (processing_template_decl && expr != error_mark_node)
return build_min (CALL_EXPR, TREE_TYPE (expr), orig_fn, orig_args);
return expr;
}
/* Returns true if ROOT (a namespace, class, or function) encloses

View File

@ -988,6 +988,10 @@ dump_decl (tree t, int flags)
dump_decl (BASELINK_FUNCTIONS (t), flags);
break;
case NON_DEPENDENT_EXPR:
dump_expr (t, flags);
break;
default:
sorry_for_unsupported_tree (t);
/* Fallthrough to error. */
@ -2028,7 +2032,11 @@ dump_expr (tree t, int flags)
dump_expr (get_first_fn (t), flags & ~TFF_EXPR_IN_PARENS);
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.
It is very important that `sorry' does not call

View File

@ -1337,157 +1337,6 @@ get_type_value (tree name)
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
C++ `&', but really something which can have its address taken,
and then act as a pointer to member, for example TYPE :: FIELD

View File

@ -2019,6 +2019,19 @@ write_expression (tree expr)
write_type (TREE_OPERAND (expr, 0));
if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
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
{
/* G++ 3.2 incorrectly put out both the "sr" code and

View File

@ -1651,6 +1651,8 @@ static tree cp_parser_sizeof_operand
(cp_parser *, enum rid);
static bool cp_parser_declares_only_class_p
(cp_parser *);
static tree cp_parser_fold_non_dependent_expr
(tree);
static bool cp_parser_friend_p
(tree);
static cp_token *cp_parser_require
@ -1661,6 +1663,8 @@ static bool cp_parser_token_starts_function_definition_p
(cp_token *);
static bool cp_parser_next_token_starts_class_definition_p
(cp_parser *);
static bool cp_parser_next_token_ends_template_argument_p
(cp_parser *);
static enum tag_types cp_parser_token_is_class_key
(cp_token *);
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");
return error_mark_node;
}
/* Fall through. */
/* An id-expression can start with either an identifier, a
`::' 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)
{
tree args = TREE_OPERAND (fns, 1);
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;
}
}
dependent_p = any_dependent_template_arguments_p (args);
/* The functions are those referred to by the
template-id. */
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
expression. Enumerators have already been handled
above. */
if (parser->constant_expression_p
if (parser->constant_expression_p)
{
/* Non-type template parameters of integral or
enumeration type. */
&& !(TREE_CODE (decl) == TEMPLATE_PARM_INDEX
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
enumeration type are OK. */
if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
;
/* Const variables or static data members of integral
or enumeration types initialized with constant
expressions (or dependent expressions - in this case
the check will be done at instantiation time). */
&& !(TREE_CODE (decl) == VAR_DECL
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
&& DECL_INITIAL (decl)
&& (TREE_CONSTANT (DECL_INITIAL (decl))
|| type_dependent_expression_p
(DECL_INITIAL (decl))
|| value_dependent_expression_p
(DECL_INITIAL (decl)))))
{
if (!parser->allow_non_constant_expression_p)
return cp_parser_non_constant_id_expression (decl);
parser->non_constant_expression_p = true;
expressions are OK. We also accept dependent
initializers; they may turn out to be constant at
instantiation-time. */
else if (TREE_CODE (decl) == VAR_DECL
&& CP_TYPE_CONST_P (TREE_TYPE (decl))
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
&& DECL_INITIAL (decl)
&& (TREE_CONSTANT (DECL_INITIAL (decl))
|| type_dependent_expression_p (DECL_INITIAL
(decl))
|| value_dependent_expression_p (DECL_INITIAL
(decl))))
;
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)
@ -3792,7 +3779,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|| TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
&& args)
{
tree arg;
tree identifier = 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
type-dependent. */
for (arg = args; arg; arg = TREE_CHAIN (arg))
if (type_dependent_expression_p (TREE_VALUE (arg)))
break;
if (!arg)
if (!any_type_dependent_arguments_p (args))
{
postfix_expression
= 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. */
unqualified_name_lookup_error (identifier);
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,
identifier);
else
postfix_expression = build_min_nt (LOOKUP_EXPR,
identifier);
}
else if (idk == CP_PARSER_ID_KIND_UNQUALIFIED
&& TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
@ -3845,25 +3826,31 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
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)
postfix_expression
= (build_new_method_call
(TREE_OPERAND (postfix_expression, 0),
TREE_OPERAND (postfix_expression, 1),
args, NULL_TREE,
(idk == CP_PARSER_ID_KIND_QUALIFIED
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
else if (TREE_CODE (postfix_expression) == OFFSET_REF)
{
tree instance = TREE_OPERAND (postfix_expression, 0);
tree fn = TREE_OPERAND (postfix_expression, 1);
if (processing_template_decl
&& (type_dependent_expression_p (instance)
|| (!BASELINK_P (fn)
&& 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, args));
else if (idk == CP_PARSER_ID_KIND_QUALIFIED)
@ -3967,8 +3954,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
struct X { void f(); };
template <typename T> void f(T* t) { t->X::f(); }
Even though "t" is dependent, "X::f" is not and has
except that for a BASELINK there is no need to
Even though "t" is dependent, "X::f" is not and has
been resolved to a BASELINK; there is no need to
include scope information. */
/* 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 *");
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 PREDECREMENT_EXPR:
@ -4354,9 +4342,6 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
case TRUTH_NOT_EXPR:
return finish_unary_op_expr (unary_operator, cast_expression);
case BIT_NOT_EXPR:
return build_x_unary_op (BIT_NOT_EXPR, cast_expression);
default:
abort ();
return error_mark_node;
@ -5293,7 +5278,6 @@ static tree
cp_parser_expression (cp_parser* parser)
{
tree expression = NULL_TREE;
bool saw_comma_p = false;
while (true)
{
@ -5306,45 +5290,23 @@ cp_parser_expression (cp_parser* parser)
save it away. */
if (!expression)
expression = assignment_expression;
/* Otherwise, chain the expressions together. It is unclear why
we do not simply build COMPOUND_EXPRs as we go. */
else
expression = tree_cons (NULL_TREE,
assignment_expression,
expression);
expression = build_x_compound_expr (expression,
assignment_expression);
/* If the next token is not a comma, then we are done with the
expression. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
break;
/* Consume the `,'. */
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. */
if (parser->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;
}
expression = build_x_compound_expr (nreverse (expression));
}
return expression;
@ -5356,8 +5318,9 @@ cp_parser_expression (cp_parser* parser)
conditional-expression
If ALLOW_NON_CONSTANT_P a non-constant expression is silently
accepted. In that case *NON_CONSTANT_P is set to TRUE. If
ALLOW_NON_CONSTANT_P is false, NON_CONSTANT_P should be NULL. */
accepted. If ALLOW_NON_CONSTANT_P is true and the expression is not
constant, *NON_CONSTANT_P is set to TRUE. If ALLOW_NON_CONSTANT_P
is false, NON_CONSTANT_P should be NULL. */
static tree
cp_parser_constant_expression (cp_parser* parser,
@ -5547,7 +5510,7 @@ cp_parser_labeled_statement (cp_parser* parser)
cp_lexer_consume_token (parser->lexer);
/* Parse the constant-expression. */
expr = cp_parser_constant_expression (parser,
/*allow_non_constant=*/false,
/*allow_non_constant_p=*/false,
NULL);
/* Create the label. */
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
id-expression -- except that the qualified id-expression is
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
cp_parser_template_argument (cp_parser* parser)
{
tree argument;
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
try each alternative in order.
@ -8073,8 +8044,7 @@ cp_parser_template_argument (cp_parser* parser)
argument = cp_parser_type_id (parser);
/* If the next token isn't a `,' or a `>', then this argument wasn't
really finished. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
&& cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER))
if (!cp_parser_next_token_ends_template_argument_p (parser))
cp_parser_error (parser, "expected template-argument");
/* If that worked, we're done. */
if (cp_parser_parse_definitely (parser))
@ -8088,8 +8058,7 @@ cp_parser_template_argument (cp_parser* parser)
&template_p);
/* If the next token isn't a `,' or a `>', then this argument wasn't
really finished. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
&& cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER))
if (!cp_parser_next_token_ends_template_argument_p (parser))
cp_parser_error (parser, "expected template-argument");
if (!cp_parser_error_occurred (parser))
{
@ -8104,8 +8073,101 @@ cp_parser_template_argument (cp_parser* parser)
}
if (cp_parser_parse_definitely (parser))
return argument;
/* It must be an assignment-expression. */
return cp_parser_assignment_expression (parser);
/* It must be a non-type argument. There permitted cases are given
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.
@ -8914,7 +8976,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
cp_lexer_consume_token (parser->lexer);
/* Parse the value. */
value = cp_parser_constant_expression (parser,
/*allow_non_constant=*/false,
/*allow_non_constant_p=*/false,
NULL);
}
else
@ -9919,29 +9981,8 @@ cp_parser_direct_declarator (cp_parser* parser,
= cp_parser_constant_expression (parser,
/*allow_non_constant=*/true,
&non_constant_p);
/* If we're in a template, but the constant-expression
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
&& !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;
}
if (!non_constant_p)
bounds = cp_parser_fold_non_dependent_expr (bounds);
}
else
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));
}
/* 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.
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);
}
/* 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,
or none_type otherwise. */

View File

@ -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 eq_local_specializations (const void *, const void *);
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_expr (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))
return error_mark_node;
if (processing_template_decl)
arg = maybe_fold_nontype_arg (arg);
if (!uses_template_parms (arg) && !uses_template_parms (t))
/* We used to call digest_init here. However, digest_init
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_args = TREE_OPERAND (fns, 1);
fns = TREE_OPERAND (fns, 0);
template_args = tsubst_copy (template_args, args,
complain, in_decl);
maybe_fold_nontype_args (template_args);
template_args = tsubst_copy_and_build (template_args, args,
complain, in_decl);
}
name = DECL_NAME (get_first_fn (fns));
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
@ -8003,30 +7998,17 @@ tsubst_copy_and_build (tree t,
case PREDECREMENT_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 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:
if (TREE_TYPE (t))
return t;
return build_x_unary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case TRUTH_NOT_EXPR:
case CONVERT_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
return (build_x_unary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl)));
case ADDR_EXPR:
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);
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 MINUS_EXPR:
case MULT_EXPR:
@ -8119,15 +8089,25 @@ tsubst_copy_and_build (tree t,
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
{
tree r =
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl);
if (!TYPE_P (r))
return TREE_CODE (t) == SIZEOF_EXPR ?
expr_sizeof (r) : c_alignof_expr (r);
else
return cxx_sizeof_or_alignof_type (r, TREE_CODE (t), true);
}
op1 = TREE_OPERAND (t, 0);
if (!args)
{
/* When there are no ARGS, we are trying to evaluate a
non-dependent expression from the parser. Trying to do
the substitutions may not work. */
if (!TYPE_P (op1))
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:
return build_x_modify_expr
@ -8162,15 +8142,11 @@ tsubst_copy_and_build (tree t,
DELETE_EXPR_USE_GLOBAL (t));
case COMPOUND_EXPR:
{
if (tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl)
== NULL_TREE)
return build_x_compound_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl));
else
abort ();
}
return (build_x_compound_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl)));
case CALL_EXPR:
{
@ -8210,25 +8186,23 @@ tsubst_copy_and_build (tree t,
complain, in_decl);
if (BASELINK_P (function))
return build_call_from_tree (function, call_args, 1);
else
{
if (call_args != NULL_TREE && koenig_name)
function = lookup_arg_dependent (koenig_name,
function,
call_args);
qualified_p = 1;
if (TREE_CODE (function) == OFFSET_REF)
return build_offset_ref_call_from_tree (function, call_args);
if (TREE_CODE (function) == COMPONENT_REF)
return (build_new_method_call
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
return finish_call_expr (function, call_args,
/*disallow_virtual=*/qualified_p);
}
if (call_args != NULL_TREE && koenig_name)
function = lookup_arg_dependent (koenig_name,
function,
call_args);
if (TREE_CODE (function) == OFFSET_REF)
return build_offset_ref_call_from_tree (function, call_args);
if (TREE_CODE (function) == COMPONENT_REF)
return (build_new_method_call
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
return finish_call_expr (function, call_args,
/*disallow_virtual=*/qualified_p);
}
case COND_EXPR:
@ -8389,6 +8363,11 @@ tsubst_copy_and_build (tree t,
case VAR_DECL:
if (args)
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);
case VA_ARG_EXPR:
@ -11491,26 +11470,46 @@ value_dependent_expression_p (tree expression)
with an expression that is value-dependent. */
if (TREE_CODE (expression) == VAR_DECL
&& DECL_INITIAL (expression)
&& INTEGRAL_OR_ENUMERATION_TYPE_P (expression)
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (expression))
&& value_dependent_expression_p (DECL_INITIAL (expression)))
return true;
/* These expressions are value-dependent if the type to which the
cast occurs is dependent or the expression being casted is
value-dependent. */
if ((TREE_CODE (expression) == DYNAMIC_CAST_EXPR
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|| TREE_CODE (expression) == CONST_CAST_EXPR
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|| TREE_CODE (expression) == CAST_EXPR)
&& (dependent_type_p (TREE_TYPE (expression))
|| value_dependent_expression_p (TREE_OPERAND (expression, 0))))
return true;
/* A `sizeof' expression where the sizeof operand is a type is
value-dependent if the type is dependent. If the type was not
dependent, we would no longer have a SIZEOF_EXPR, so any
SIZEOF_EXPR is dependent. */
if (TREE_CODE (expression) == SIZEOF_EXPR)
return true;
if (TREE_CODE (expression) == DYNAMIC_CAST_EXPR
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|| TREE_CODE (expression) == CONST_CAST_EXPR
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
|| TREE_CODE (expression) == CAST_EXPR)
{
if (dependent_type_p (TREE_TYPE (expression)))
return true;
/* A functional cast has a list of operands. */
expression = TREE_OPERAND (expression, 0);
if (TREE_CODE (expression) == TREE_LIST)
{
do
{
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
value-dependent. */
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) == CAST_EXPR)
return dependent_type_p (TREE_TYPE (expression));
/* The types of these expressions depends only on the type created
by the expression. */
else if (TREE_CODE (expression) == NEW_EXPR
|| TREE_CODE (expression) == VEC_NEW_EXPR)
if (TREE_CODE (expression) == NEW_EXPR
|| TREE_CODE (expression) == VEC_NEW_EXPR)
{
/* For NEW_EXPR tree nodes created inside a template, either
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)))))
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)));
}
/* 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. */
bool
static bool
dependent_template_arg_p (tree arg)
{
if (!processing_template_decl)
@ -11622,18 +11663,36 @@ dependent_template_arg_p (tree 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
dependent_template_id_p (tree tmpl, tree args)
bool
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;
}
@ -11646,12 +11705,24 @@ dependent_template_p (tree tmpl)
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
|| TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
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. */
if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
return dependent_type_p (DECL_CONTEXT (tmpl));
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
TYPENAME_TYPE corresponds. Returns ERROR_MARK_NODE if no such TYPE
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;
}
/* 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"

View File

@ -1449,8 +1449,12 @@ finish_stmt_expr (tree rtl_expr)
tree result;
/* If the last thing in the statement-expression was not an
expression-statement, then it has type `void'. */
if (!last_expr_type)
expression-statement, then it has type `void'. In a template, we
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;
result = build_min (STMT_EXPR, last_expr_type, last_tree);
TREE_SIDE_EFFECTS (result) = 1;
@ -1482,16 +1486,32 @@ finish_stmt_expr (tree rtl_expr)
tree
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)
return error_mark_node;
if (processing_template_decl)
return build_nt (CALL_EXPR, fn, args, NULL_TREE);
/* ARGS should be a list of arguments. */
my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
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
function (rather than a BASELINK) if an unqualified name was used
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))
{
tree object;
@ -1551,17 +1572,22 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
object = build_dummy_object (DECL_CONTEXT (representative_fn));
}
return build_new_method_call (object, fn, args, NULL_TREE,
(disallow_virtual
? LOOKUP_NONVIRTUAL : 0));
if (processing_template_decl)
{
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))
/* 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)
{
tree result;
if (args)
error ("arguments to destructor are not allowed");
/* 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,
TREE_OPERAND (fn, 0));
TREE_SIDE_EFFECTS (result) = 1;
return result;
}
else if (CLASS_TYPE_P (TREE_TYPE (fn)))
{
/* If the "function" is really an object of class type, it might
have an overloaded `operator ()'. */
tree result;
result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
if (result)
return result;
}
/* If the "function" is really an object of class type, it might
have an overloaded `operator ()'. */
result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
if (!result)
/* A call where the function is unknown. */
result = build_function_call (fn, args);
/* A call where the function is unknown. */
return build_function_call (fn, args);
if (processing_template_decl)
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

View File

@ -174,6 +174,14 @@ lvalue_p_1 (tree ref,
return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
? 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:
break;
}

View File

@ -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);
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;
@ -1446,7 +1446,7 @@ tree
expr_sizeof (tree e)
{
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
&& DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
@ -2015,17 +2015,36 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
tree
finish_class_member_access_expr (tree object, tree name)
{
tree expr;
tree object_type;
tree member;
tree access_path = NULL_TREE;
tree orig_object = object;
tree orig_name = name;
if (object == error_mark_node || name == error_mark_node)
return error_mark_node;
if (processing_template_decl)
return build_min_nt (COMPONENT_REF, object, name);
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)
{
object = convert_from_reference (object);
@ -2057,6 +2076,7 @@ finish_class_member_access_expr (tree object, tree name)
{
bool is_template_id = false;
tree template_args = NULL_TREE;
tree scope;
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)
{
tree scope;
/* A qualified name. The qualifying class or namespace `S' has
already been looked up; it is either a TYPE or a
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);
if (!access_path || access_path == 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)
member = lookup_destructor (object, /*scope=*/NULL_TREE, name);
else if (TREE_CODE (name) == IDENTIFIER_NODE)
else
{
/* An unqualified name. */
member = lookup_member (object_type, name, /*protect=*/1,
scope = NULL_TREE;
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);
if (member == NULL_TREE)
{
error ("'%D' has no member named '%E'", object_type, name);
return error_mark_node;
}
else if (member == error_mark_node)
if (member == 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)
{
tree template = member;
if (BASELINK_P (template))
BASELINK_FUNCTIONS (template)
= build_nt (TEMPLATE_ID_EXPR,
BASELINK_FUNCTIONS (template),
template_args);
template = lookup_template_function (template, template_args);
else
{
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))
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);
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
@ -2196,18 +2196,27 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
Must also handle REFERENCE_TYPEs for C++. */
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;
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);
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 build_indirect_ref (ptr, errorstring);
}
tree
@ -2826,192 +2835,33 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
tree
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)
return build_min_nt (code, arg1, arg2);
{
if (type_dependent_expression_p (arg1)
|| type_dependent_expression_p (arg2))
return build_min_nt (code, arg1, arg2);
arg1 = build_non_dependent_expr (arg1);
arg2 = build_non_dependent_expr (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;
expr = build_m_component_ref (arg1, arg2);
else
{
struct z_candidate *cand;
tree op0_type;
tree op1_type;
tree op2_type;
expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
/* 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;
}
}
if (processing_template_decl && expr != error_mark_node)
return build_min (code, TREE_TYPE (expr), orig_arg1, orig_arg2);
return build_min (code, type, op0, op1, op2, NULL_TREE);
return expr;
}
#endif
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
This function differs from `build' in several ways:
@ -3839,11 +3689,18 @@ pointer_diff (register tree op0, register tree op1, register tree ptrtype)
tree
build_x_unary_op (enum tree_code code, tree xarg)
{
tree orig_expr = xarg;
tree exp;
int ptrmem = 0;
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
error message. */
@ -3854,15 +3711,8 @@ build_x_unary_op (enum tree_code code, tree xarg)
|| (TREE_CODE (xarg) == OFFSET_REF)))
/* don't look for a function */;
else
{
tree rval;
rval = build_new_op (code, LOOKUP_NORMAL, xarg,
NULL_TREE, NULL_TREE);
if (rval || code != ADDR_EXPR)
return rval;
}
if (code == ADDR_EXPR)
exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE);
if (!exp && code == ADDR_EXPR)
{
/* A pointer to member-function can be formed only by saying
&X::mf. */
@ -3896,16 +3746,17 @@ build_x_unary_op (enum tree_code code, tree xarg)
TREE_OPERAND (xarg, 0),
ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE));
PTRMEM_OK_P (xarg) = ptrmem;
}
}
}
else if (TREE_CODE (xarg) == TARGET_EXPR)
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;
}
@ -4631,53 +4482,76 @@ cxx_mark_addressable (tree exp)
tree
build_x_conditional_expr (tree ifexp, tree op1, tree op2)
{
if (processing_template_decl)
return build_min_nt (COND_EXPR, ifexp, op1, op2);
tree orig_ifexp = ifexp;
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,
this function just builds an expression list. */
tree
build_x_compound_expr (tree list)
build_x_compound_expr (tree op1, tree op2)
{
tree rest = TREE_CHAIN (list);
tree result;
tree orig_op1 = op1;
tree orig_op2 = op2;
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. */
/* 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 (TREE_VALUE(list)) == CONVERT_EXPR
&& VOID_TYPE_P (TREE_TYPE (TREE_VALUE(list)))))
warning("left-hand operand of comma expression has no effect");
if (type_dependent_expression_p (op1)
|| type_dependent_expression_p (op2))
return build_min_nt (COMPOUND_EXPR, op1, op2);
op1 = build_non_dependent_expr (op1);
op2 = build_non_dependent_expr (op2);
}
#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
(tree_cons (NULL_TREE, TREE_VALUE (list),
build_tree_list (NULL_TREE,
build_x_compound_expr (rest))));
result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE);
if (!result)
{
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

View File

@ -980,44 +980,48 @@ build_scoped_ref (tree datum, tree basetype, tree* binfo_p)
delegation is detected. */
tree
build_x_arrow (tree datum)
build_x_arrow (tree expr)
{
tree orig_expr = expr;
tree types_memoized = NULL_TREE;
register tree rval = datum;
tree type = TREE_TYPE (rval);
tree type = TREE_TYPE (expr);
tree last_rval = NULL_TREE;
if (type == error_mark_node)
return error_mark_node;
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)
{
rval = convert_from_reference (rval);
type = TREE_TYPE (rval);
expr = convert_from_reference (expr);
type = TREE_TYPE (expr);
}
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)))
{
if (rval == error_mark_node)
if (expr == 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");
return error_mark_node;
}
else
{
types_memoized = tree_cons (NULL_TREE, TREE_TYPE (rval),
types_memoized = tree_cons (NULL_TREE, TREE_TYPE (expr),
types_memoized);
}
last_rval = rval;
last_rval = expr;
}
if (last_rval == NULL_TREE)
@ -1030,10 +1034,17 @@ build_x_arrow (tree datum)
last_rval = convert_from_reference (last_rval);
}
else
last_rval = decay_conversion (rval);
last_rval = decay_conversion (expr);
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)
error ("result of `operator->()' yields non-pointer result");

View File

@ -2908,7 +2908,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
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) == '<'
|| TREE_CODE_CLASS (code) == '1'
|| TREE_CODE_CLASS (code) == '2')

View File

@ -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>
* gcc.dg/const-elim-1.c (dg-final): Change regexp to match labels

View File

@ -4,8 +4,8 @@ enum E { e = 3 };
template <int I> struct S {};
template <int I> void f (S<e + int (3.7)>) {}
template void f<7>(S<e + int (3.7)>); // { dg-warning "mangle" }
template <int I> void f (S<I + e + int (3.7)>) {}
template void f<7>(S<7 + e + int (3.7)>); // { dg-warning "mangle" }
template <int I> void g (S<e + int (3.7)>) {}
template void g<7>(S<e + int (3.7)>); // { dg-warning "mangle" }
template <int I> void g (S<I + e + int (3.7)>) {}
template void g<7>(S<7 + e + int (3.7)>); // { dg-warning "mangle" }

View File

@ -8,19 +8,17 @@ template<const A* a> class C {};
template<const B* b> class D {};
template<B* b> class E {};
template<const B* b> void f(D<b> &, C<static_cast<const A*>(b)> &) {}
template<const B* b> void g(D<b> &, E<const_cast<B*>(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)> &) {} // { dg-error "" }
B b;
int main()
{
C<static_cast<const A*>(&b)> c;
C<static_cast<const A*>(&b)> c; // { dg-error "" }
D<&b> d;
E<const_cast<B*>(&b)> e;
f(d, c);
g(d, e);
E<const_cast<B*>(&b)> e; // { dg-error "" }
f(d, c); // { dg-error "" }
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\]" } }

View File

@ -7,7 +7,7 @@ main() {
int a = 4;
int b = 5;
int (*x)[b] = new int[a][b];
int (*x)[b] = new int[a][b]; // { dg-error "" }
x[2][1] = 7;

View File

@ -68,7 +68,7 @@ template<typename=void>
struct adaptor {
adaptor (matrix<> &m) : m(&m), upper_ (1) {}
int size1 () const { return m->size1 (); }
int size1 () const;
int size2 () const { return 3; }
int lower () const { return 1; }
int upper () const { return upper_; }

View File

@ -0,0 +1,4 @@
template <int I>
void f();
void g() { f<(3, 2)>(); } // { dg-error "" }

View File

@ -21,9 +21,9 @@ namespace std
Foo (__alignof__ (x));
Foo (x->~I ());
// Foo (typeid (I));
Foo (delete x);
Foo (delete[] x);
Foo (throw x);
Foo (delete x); // { dg-error "" }
Foo (delete[] x); // { dg-error "" }
Foo (throw x); // { dg-error "" }
}
}

View File

@ -1,4 +1,4 @@
// { dg-do assemble }
// { dg-do compile }
// Origin: Mark Mitchell <mark@codesourcery.com>
template <int> struct S1{};
@ -7,5 +7,5 @@ struct S2 { int i; };
template <class T>
void f(S2 s2) {
S1<s2.i> s1;
S1<s2.i> s1; // { dg-error "" }
}

View File

@ -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>
* gnu/java/awt/peer/gtk/GtkComponentPeer.java,

View File

@ -71,7 +71,9 @@ typedef JArray<jstring> *jstringArray;
extern java::lang::Class _Jv_byteClass, _Jv_shortClass, _Jv_intClass,
_Jv_longClass, _Jv_booleanClass, _Jv_charClass, _Jv_floatClass,
_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" jobject _Jv_NewPrimArray (jclass eltype, jint count);