aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-07-09 08:48:08 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-07-09 08:48:08 +0000
commitd17811fd1aad24d0f47d0b20679753b23803848b (patch)
tree1246373b84fbf4bb96eed29b458823d826bd18da /gcc
parent844c00ed1626fba3304289f5f8c3531620b24d5f (diff)
downloadgcc-d17811fd1aad24d0f47d0b20679753b23803848b.zip
gcc-d17811fd1aad24d0f47d0b20679753b23803848b.tar.gz
gcc-d17811fd1aad24d0f47d0b20679753b23803848b.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/cp/ChangeLog73
-rw-r--r--gcc/cp/call.c27
-rw-r--r--gcc/cp/cp-tree.def10
-rw-r--r--gcc/cp/cp-tree.h11
-rw-r--r--gcc/cp/decl2.c192
-rw-r--r--gcc/cp/error.c10
-rw-r--r--gcc/cp/init.c151
-rw-r--r--gcc/cp/mangle.c13
-rw-r--r--gcc/cp/parser.c359
-rw-r--r--gcc/cp/pt.c329
-rw-r--r--gcc/cp/semantics.c68
-rw-r--r--gcc/cp/tree.c8
-rw-r--r--gcc/cp/typeck.c422
-rw-r--r--gcc/cp/typeck2.c37
-rw-r--r--gcc/fold-const.c3
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle17.C8
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle4.C14
-rw-r--r--gcc/testsuite/g++.dg/debug/debug7.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/stack1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/template7.C4
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-expr1.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash41.C4
24 files changed, 934 insertions, 835 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d5ee8c6..e5cf6bb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a4b9aea..8d83247 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index fbf5c06..6659592 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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;
}
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index e988a4e..f9819ec 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -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)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9d383cf..58eabc3 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 7a2399a..c77e503 100644
--- a/gcc/cp/decl2.c
+++ b/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);
+ {
+ 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);
+ 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);
+ 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) && (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 (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");
+ 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);
+ expr = 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;
+
+ orig_fn = fn;
+ orig_args = args;
- my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725);
+ 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
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index a9f5b15..79803d2 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index f89b424..4a11b43 100644
--- a/gcc/cp/init.c
+++ b/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
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 63c58ba..29fd523 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 27e73cb..19f55f4 100644
--- a/gcc/cp/parser.c
+++ b/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)
+ if (TREE_CODE (postfix_expression) == COMPONENT_REF)
{
- postfix_expression = build_nt (CALL_EXPR,
- postfix_expression,
- args);
- break;
+ 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)));
}
-
- 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)
+ 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. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index abb51b2..4d650c5 100644
--- a/gcc/cp/pt.c
+++ b/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);
-
- 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);
- }
+ qualified_p = 1;
+
+ 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 the ARG (a template argument) is dependent. */
+/* 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. */
+
+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"
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index cc1e2ea..db9e4d2 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 975c396..366ea3a 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e6abb3d..6d499d6 100644
--- a/gcc/cp/typeck.c
+++ b/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;
+ object_type = TREE_TYPE (object);
+
if (processing_template_decl)
- return build_min_nt (COMPONENT_REF, object, name);
+ {
+ 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);
+ }
- object_type = TREE_TYPE (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
+ {
+ scope = NULL_TREE;
+ access_path = object_type;
+ }
+
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
+ member = lookup_destructor (object, scope, name);
+ else
{
- /* An unqualified name. */
- member = lookup_member (object_type, name, /*protect=*/1,
+ /* 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)
{
- if (processing_template_decl)
- return build_min_nt (code, arg1, arg2);
-
- if (code == DOTSTAR_EXPR)
- return build_m_component_ref (arg1, arg2);
-
- return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
-}
-
-#if 0
+ tree orig_arg1;
+ tree orig_arg2;
+ tree expr;
-tree
-build_template_expr (enum tree_code code, tree op0, tree op1, tree op2)
-{
- tree type;
+ orig_arg1 = arg1;
+ orig_arg2 = arg2;
- /* If any of the operands is erroneous the result is erroneous too. */
- if (error_operand_p (op0)
- || (op1 && error_operand_p (op1))
- || (op2 && error_operand_p (op2)))
- return error_mark_node;
-
- if (dependent_type_p (TREE_TYPE (op0))
- || (op1 && dependent_type_p (TREE_TYPE (op1)))
- || (op2 && dependent_type_p (TREE_TYPE (op2))))
- /* If at least one operand has a dependent type, we cannot
- determine the type of the expression until instantiation time. */
- type = NULL_TREE;
- else
+ if (processing_template_decl)
{
- struct z_candidate *cand;
- tree op0_type;
- tree op1_type;
- tree op2_type;
-
- /* 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; ... }
+ 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);
+ }
- we can tell that the type of "s" is non-dependent.
+ if (code == DOTSTAR_EXPR)
+ expr = build_m_component_ref (arg1, arg2);
+ else
+ expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
- 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);
+ {
+ 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);
+ }
- 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 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
+ 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)));
+ }
- return build_compound_expr
- (tree_cons (NULL_TREE, TREE_VALUE (list),
- build_tree_list (NULL_TREE,
- build_x_compound_expr (rest))));
+ 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
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index edb9f5d..6a14fec 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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");
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e4f57b8..e268055 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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')
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9ee1e57..859e8a5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/abi/mangle17.C b/gcc/testsuite/g++.dg/abi/mangle17.C
index 1da6dea..6f8e387 100644
--- a/gcc/testsuite/g++.dg/abi/mangle17.C
+++ b/gcc/testsuite/g++.dg/abi/mangle17.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/abi/mangle4.C b/gcc/testsuite/g++.dg/abi/mangle4.C
index ec65654..d4b5936 100644
--- a/gcc/testsuite/g++.dg/abi/mangle4.C
+++ b/gcc/testsuite/g++.dg/abi/mangle4.C
@@ -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\]" } }
diff --git a/gcc/testsuite/g++.dg/debug/debug7.C b/gcc/testsuite/g++.dg/debug/debug7.C
index 78faa20..31d47ed 100644
--- a/gcc/testsuite/g++.dg/debug/debug7.C
+++ b/gcc/testsuite/g++.dg/debug/debug7.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/opt/stack1.C b/gcc/testsuite/g++.dg/opt/stack1.C
index bb6159c..7fac18d 100644
--- a/gcc/testsuite/g++.dg/opt/stack1.C
+++ b/gcc/testsuite/g++.dg/opt/stack1.C
@@ -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_; }
diff --git a/gcc/testsuite/g++.dg/parse/template7.C b/gcc/testsuite/g++.dg/parse/template7.C
new file mode 100644
index 0000000..b13e3ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/template7.C
@@ -0,0 +1,4 @@
+template <int I>
+void f();
+
+void g() { f<(3, 2)>(); } // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/template/dependent-expr1.C b/gcc/testsuite/g++.dg/template/dependent-expr1.C
index 079f033..e29b76d 100644
--- a/gcc/testsuite/g++.dg/template/dependent-expr1.C
+++ b/gcc/testsuite/g++.dg/template/dependent-expr1.C
@@ -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 "" }
}
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash41.C b/gcc/testsuite/g++.old-deja/g++.pt/crash41.C
index a3d8088..fc7f7b5 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/crash41.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash41.C
@@ -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 "" }
}