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>
|
||||
|
||||
* 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>
|
||||
|
||||
* 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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
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
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
151
gcc/cp/init.c
151
gcc/cp/init.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
361
gcc/cp/parser.c
361
gcc/cp/parser.c
|
@ -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. */
|
||||
|
||||
|
|
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 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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
422
gcc/cp/typeck.c
422
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);
|
||||
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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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\]" } }
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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_; }
|
||||
|
|
|
@ -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 (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 "" }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 "" }
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue