aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-01-30 07:24:02 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-01-30 07:24:02 +0000
commit14d22dd6675f2225b5de7c0e591893f84fb6b9e0 (patch)
tree9b52cc234bf9b52b7127dba18c43be2715c995b2 /gcc
parent825db093dfec43ee507e96de62db43f896047702 (diff)
downloadgcc-14d22dd6675f2225b5de7c0e591893f84fb6b9e0.zip
gcc-14d22dd6675f2225b5de7c0e591893f84fb6b9e0.tar.gz
gcc-14d22dd6675f2225b5de7c0e591893f84fb6b9e0.tar.bz2
c-common.c (builtin_define_float_constants): Define __<TYPE>_HAS_INFINITY__ and __<TYPE>_HAS_QUIET_NAN__.
* c-common.c (builtin_define_float_constants): Define __<TYPE>_HAS_INFINITY__ and __<TYPE>_HAS_QUIET_NAN__. * call.c (build_field_call): Use build_new_op, not build_opfncall. (prep_operand): New function. (build_new_op): Use it. Remove dead code. * class.c (pushclass): Change "modify" parameter type from int to bool. (currently_open_class): Use same_type_p, not pointer equality. (push_nested_class): Adjust calls to pushclass, remove modify parameter. * cp-tree.h (INTEGRAL_OR_ENUMERATION_TYPE_P): New macro. (pushclass): Change prototype. (push_nested_class): Likewise. (grokoptypename): Remove. (build_opfncall): Remove. (value_dependent_expression_p): Declare. (resolve_typename_type): Likewise. (resolve_typename_type_in_current_instantiation): Likewise. (enter_scope_of): Remove. (tsubst): Remove. (tsubst_expr): Likewise. (tsubst_copy): Likewise. (tsubst_copy_and_build): Likewise. * decl.c (warn_about_implicit_typename_lookup): Remove. (finish_case_label): Return error_mark_node for erroneous labels. (start_decl): Adjust calls to push_nested_class. (grokfndecl): Call push_scope/pop_scope around call to duplicate_decls. (grokdeclarator): Do not call tsubst. (start_function): Adjust calls to push_nested_class. * decl2.c (grok_array_decl): Use build_new_op, not build_opfncall. (check_classfn): Use push_scope/pop_scope around type comparisions. (grokoptypename): Remove. (push_sscope): Adjust call to push_nested_class. * error.c (dump_type): Show cv-qualification of typename types. * init.c (build_member_call): Use build_new_op, not build_opfncall. * method.c (build_opfncall): Remove. * parser.c (cp_parser): Add allow_non_constant_expression_p and non_constant_expression_p. (cp_parser_constant_expression): Adjust prototype. (cp_parser_resolve_typename_type): Remove. (cp_parser_non_constant_expression): New function. (cp_parser_non_constant_id_expression): Likewise. (cp_parser_new): Set allow_non_constant_expression_p and non_constant_expression_p. (cp_parser_primary_expression): Reject `this' and `va_arg' in constant-expressions. Note that dependent names aren't really constant. (cp_parser_postfix_expression): Reject conversions to non-integral types in constant-expressions. Neither are increments or decrements. (cp_parser_unary_expression): Reject increments and decrements in constant-expressions. (cp_parser_direct_new_declarator): Adjust call to cp_parser_constant_expression. (cp_parser_cast_expression): Reject conversions to non-integral types in constant-expressions. (cp_parser_assignment_expression): Rejects assignments in constant-expressions. (cp_parser_expression): Reject commas in constant-expressions. (cp_parser_labeled_statement): Adjust call to cp_parser_constant_expression. (cp_parser_direct_declarator): Simplify array bounds, even in templates, when they are non-dependent. Use resolve_typename_type, not cp_parser_resolve_typename_type. (cp_parser_class_head): Use resolve_typename_type, not cp_parser_resolve_typename_type. (cp_parser_member_declaration): Adjust call to cp_parser_constant_expression. (cp_parser_constant_initializer): Likewise. (cp_parser_constructor_declarator): Use resolve_typename_type, not cp_parser_resolve_typename_type. (cp_parser_late_parsing_default_args): Adjust call to push_nested_class. * pt.c (tsubst): Give it internal linkage. (tsubst_expr): Likewise. (tsubst_copy): Likewise. (tsubst_copy_and_build): Likewise. (push_access_scope_real): Likewise. (tsubst_friend_class): Likewise. (instantiate_class_template): Adjust call to pushclass. (value_dependent_expression_p): Give it external linkage. Robustify. (resolve_typename_type): New function. * semantics.c (finish_call_expr): Use build_new_op, not build_opfncall. (begin_constructor_declarator): Remove. (begin_class_definition): Adjust call to pushclass. (enter_scope_of): Remove. * typeck.c (comptypes): Resolve typename types as appropriate. (build_x_indirect_ref): Use build_new_op, not build_opfncall. (build_x_compound_expr): Likewise. (build_modify_expr): Likewise. (build_x_modify_expr): Likewise. * typeck2.c (build_x_arrow): Likewise. * g++.dg/parser/constant1.C: New test. * include/std/std_limits.h (numeric_limits<float>::has_infinity): Use __FLT_HAS_INIFINITY__ to initialize. (numeric_limits<float>::has_quiet_NaN): Likewise. (numeric_limits<double>::has_infinity): Use __DBL_HAS_INIFINITY__ to initialize. (numeric_limits<double>::has_quiet_NaN): Likewise. (numeric_limits<long double>::has_infinity): Use __LDBL_HAS_INIFINITY__ to initialize. (numeric_limits<long_double>::has_quiet_NaN): Likewise. From-SVN: r62130
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-common.c12
-rw-r--r--gcc/cp/ChangeLog97
-rw-r--r--gcc/cp/call.c63
-rw-r--r--gcc/cp/class.c22
-rw-r--r--gcc/cp/cp-tree.h19
-rw-r--r--gcc/cp/decl.c64
-rw-r--r--gcc/cp/decl2.c36
-rw-r--r--gcc/cp/error.c1
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/cp/method.c30
-rw-r--r--gcc/cp/parser.c380
-rw-r--r--gcc/cp/pt.c123
-rw-r--r--gcc/cp/semantics.c45
-rw-r--r--gcc/cp/typeck.c200
-rw-r--r--gcc/cp/typeck2.c4
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/parse/constant1.C13
18 files changed, 776 insertions, 346 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d4a863a..54129c4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2003-01-29 Mark Mitchell <mark@codesourcery.com>
+
+ * c-common.c (builtin_define_float_constants): Define
+ __<TYPE>_HAS_INFINITY__ and __<TYPE>_HAS_QUIET_NAN__.
+
2003-01-30 Kazu Hirata <kazu@cs.umass.edu>
* config/sh/lib1funcs.asm: Fix comment typos.
diff --git a/gcc/c-common.c b/gcc/c-common.c
index cf7fb07..7c6fc78 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -4896,6 +4896,18 @@ builtin_define_float_constants (name_prefix, fp_suffix, type)
sprintf (buf, "0.0%s", fp_suffix);
builtin_define_with_value (name, buf, 0);
}
+
+ /* For C++ std::numeric_limits<T>::has_infinity. */
+ sprintf (name, "__%s_HAS_INFINITY__", name_prefix);
+ builtin_define_with_int_value (name,
+ MODE_HAS_INFINITIES (TYPE_MODE (type)));
+ /* For C++ std::numeric_limits<T>::has_quiet_NaN. We do not have a
+ predicate to distinguish a target that has both quiet and
+ signalling NaNs from a target that has only quiet NaNs or only
+ signalling NaNs, so we assume that a target that has any kind of
+ NaN has quiet NaNs. */
+ sprintf (name, "__%s_HAS_QUIET_NAN__", name_prefix);
+ builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type)));
}
/* Hook that registers front end and target-specific built-ins. */
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 64adf91..1b00808 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,100 @@
+2003-01-29 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_field_call): Use build_new_op, not build_opfncall.
+ (prep_operand): New function.
+ (build_new_op): Use it. Remove dead code.
+ * class.c (pushclass): Change "modify" parameter type from int to
+ bool.
+ (currently_open_class): Use same_type_p, not pointer equality.
+ (push_nested_class): Adjust calls to pushclass, remove modify
+ parameter.
+ * cp-tree.h (INTEGRAL_OR_ENUMERATION_TYPE_P): New macro.
+ (pushclass): Change prototype.
+ (push_nested_class): Likewise.
+ (grokoptypename): Remove.
+ (build_opfncall): Remove.
+ (value_dependent_expression_p): Declare.
+ (resolve_typename_type): Likewise.
+ (resolve_typename_type_in_current_instantiation): Likewise.
+ (enter_scope_of): Remove.
+ (tsubst): Remove.
+ (tsubst_expr): Likewise.
+ (tsubst_copy): Likewise.
+ (tsubst_copy_and_build): Likewise.
+ * decl.c (warn_about_implicit_typename_lookup): Remove.
+ (finish_case_label): Return error_mark_node for erroneous labels.
+ (start_decl): Adjust calls to push_nested_class.
+ (grokfndecl): Call push_scope/pop_scope around call to
+ duplicate_decls.
+ (grokdeclarator): Do not call tsubst.
+ (start_function): Adjust calls to push_nested_class.
+ * decl2.c (grok_array_decl): Use build_new_op, not build_opfncall.
+ (check_classfn): Use push_scope/pop_scope around type comparisions.
+ (grokoptypename): Remove.
+ (push_sscope): Adjust call to push_nested_class.
+ * error.c (dump_type): Show cv-qualification of typename types.
+ * init.c (build_member_call): Use build_new_op, not
+ build_opfncall.
+ * method.c (build_opfncall): Remove.
+ * parser.c (cp_parser): Add allow_non_constant_expression_p and
+ non_constant_expression_p.
+ (cp_parser_constant_expression): Adjust prototype.
+ (cp_parser_resolve_typename_type): Remove.
+ (cp_parser_non_constant_expression): New function.
+ (cp_parser_non_constant_id_expression): Likewise.
+ (cp_parser_new): Set allow_non_constant_expression_p and
+ non_constant_expression_p.
+ (cp_parser_primary_expression): Reject `this' and `va_arg' in
+ constant-expressions. Note that dependent names aren't really
+ constant.
+ (cp_parser_postfix_expression): Reject conversions to non-integral
+ types in constant-expressions. Neither are increments or
+ decrements.
+ (cp_parser_unary_expression): Reject increments and decrements in
+ constant-expressions.
+ (cp_parser_direct_new_declarator): Adjust call to
+ cp_parser_constant_expression.
+ (cp_parser_cast_expression): Reject conversions to non-integral
+ types in constant-expressions.
+ (cp_parser_assignment_expression): Rejects assignments in
+ constant-expressions.
+ (cp_parser_expression): Reject commas in constant-expressions.
+ (cp_parser_labeled_statement): Adjust call to
+ cp_parser_constant_expression.
+ (cp_parser_direct_declarator): Simplify array bounds, even in
+ templates, when they are non-dependent. Use
+ resolve_typename_type, not cp_parser_resolve_typename_type.
+ (cp_parser_class_head): Use resolve_typename_type, not
+ cp_parser_resolve_typename_type.
+ (cp_parser_member_declaration): Adjust call to
+ cp_parser_constant_expression.
+ (cp_parser_constant_initializer): Likewise.
+ (cp_parser_constructor_declarator): Use resolve_typename_type, not
+ cp_parser_resolve_typename_type.
+ (cp_parser_late_parsing_default_args): Adjust call to
+ push_nested_class.
+ * pt.c (tsubst): Give it internal linkage.
+ (tsubst_expr): Likewise.
+ (tsubst_copy): Likewise.
+ (tsubst_copy_and_build): Likewise.
+ (push_access_scope_real): Likewise.
+ (tsubst_friend_class): Likewise.
+ (instantiate_class_template): Adjust call to pushclass.
+ (value_dependent_expression_p): Give it external linkage.
+ Robustify.
+ (resolve_typename_type): New function.
+ * semantics.c (finish_call_expr): Use build_new_op, not
+ build_opfncall.
+ (begin_constructor_declarator): Remove.
+ (begin_class_definition): Adjust call to pushclass.
+ (enter_scope_of): Remove.
+ * typeck.c (comptypes): Resolve typename types as appropriate.
+ (build_x_indirect_ref): Use build_new_op, not build_opfncall.
+ (build_x_compound_expr): Likewise.
+ (build_modify_expr): Likewise.
+ (build_x_modify_expr): Likewise.
+ * typeck2.c (build_x_arrow): Likewise.
+
2003-01-29 Fariborz Jahanian <fjahanian@apple.com>
* pt.c (last_pending_template) Declare GTY().
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index cb0d351..440d58a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -103,6 +103,7 @@ static bool promoted_arithmetic_type_p (tree);
static tree conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *);
static tree call_builtin_trap (void);
+static tree prep_operand (tree);
tree
build_vfield_ref (tree datum, tree type)
@@ -145,8 +146,8 @@ build_field_call (tree instance_ptr, tree decl, tree parms)
return error_mark_node;
if (IS_AGGR_TYPE (TREE_TYPE (instance)))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
- instance, parms, NULL_TREE);
+ return build_new_op (CALL_EXPR, LOOKUP_NORMAL,
+ instance, parms, NULL_TREE);
else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE
|| (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
@@ -3295,6 +3296,27 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
return result;
}
+/* OPERAND is an operand to an expression. Perform necessary steps
+ required before using it. If OPERAND is NULL_TREE, NULL_TREE is
+ returned. */
+
+static tree
+prep_operand (tree operand)
+{
+ if (operand)
+ {
+ if (TREE_CODE (operand) == OFFSET_REF)
+ operand = resolve_offset_ref (operand);
+ operand = convert_from_reference (operand);
+ if (CLASS_TYPE_P (TREE_TYPE (operand))
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand)))
+ /* Make sure the template type is instantiated now. */
+ instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (operand)));
+ }
+
+ return operand;
+}
+
tree
build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
{
@@ -3310,14 +3332,6 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
|| error_operand_p (arg3))
return error_mark_node;
- /* This can happen if a template takes all non-type parameters, e.g.
- undeclared_template<1, 5, 72>a; */
- if (code == LT_EXPR && TREE_CODE (arg1) == TEMPLATE_DECL)
- {
- error ("`%D' must be declared before use", arg1);
- return error_mark_node;
- }
-
if (code == MODIFY_EXPR)
{
code2 = TREE_CODE (arg3);
@@ -3327,13 +3341,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
else
fnname = ansi_opname (code);
- if (TREE_CODE (arg1) == OFFSET_REF)
- arg1 = resolve_offset_ref (arg1);
- arg1 = convert_from_reference (arg1);
- if (CLASS_TYPE_P (TREE_TYPE (arg1))
- && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg1)))
- /* Make sure the template type is instantiated now. */
- instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)));
+ arg1 = prep_operand (arg1);
switch (code)
{
@@ -3351,24 +3359,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
break;
}
- if (arg2)
- {
- if (TREE_CODE (arg2) == OFFSET_REF)
- arg2 = resolve_offset_ref (arg2);
- arg2 = convert_from_reference (arg2);
- if (CLASS_TYPE_P (TREE_TYPE (arg2))
- && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg2)))
- instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg2)));
- }
- if (arg3)
- {
- if (TREE_CODE (arg3) == OFFSET_REF)
- arg3 = resolve_offset_ref (arg3);
- arg3 = convert_from_reference (arg3);
- if (CLASS_TYPE_P (TREE_TYPE (arg3))
- && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg3)))
- instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg3)));
- }
+ arg2 = prep_operand (arg2);
+ arg3 = prep_operand (arg3);
if (code == COND_EXPR)
{
@@ -3553,7 +3545,6 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
if (TREE_CODE (cand->fn) == FUNCTION_DECL)
{
- extern int warn_synth;
if (warn_synth
&& fnname == ansi_assopname (NOP_EXPR)
&& DECL_ARTIFICIAL (cand->fn)
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 6cdcb9a..378c637 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5758,7 +5758,7 @@ init_class_processing (void)
that name becomes `error_mark_node'. */
void
-pushclass (tree type, int modify)
+pushclass (tree type, bool modify)
{
type = TYPE_MAIN_VARIANT (type);
@@ -5880,10 +5880,11 @@ int
currently_open_class (tree t)
{
int i;
- if (t == current_class_type)
+ if (current_class_type && same_type_p (t, current_class_type))
return 1;
for (i = 1; i < current_class_depth; ++i)
- if (current_class_stack [i].type == t)
+ if (current_class_stack[i].type
+ && same_type_p (current_class_stack [i].type, t))
return 1;
return 0;
}
@@ -5912,14 +5913,13 @@ currently_open_derived_class (tree t)
}
/* When entering a class scope, all enclosing class scopes' names with
- static meaning (static variables, static functions, types and enumerators)
- have to be visible. This recursive function calls pushclass for all
- enclosing class contexts until global or a local scope is reached.
- TYPE is the enclosed class and MODIFY is equivalent with the pushclass
- formal of the same name. */
+ static meaning (static variables, static functions, types and
+ enumerators) have to be visible. This recursive function calls
+ pushclass for all enclosing class contexts until global or a local
+ scope is reached. TYPE is the enclosed class. */
void
-push_nested_class (tree type, int modify)
+push_nested_class (tree type)
{
tree context;
@@ -5935,8 +5935,8 @@ push_nested_class (tree type, int modify)
context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
if (context && CLASS_TYPE_P (context))
- push_nested_class (context, 2);
- pushclass (type, modify);
+ push_nested_class (context);
+ pushclass (type, true);
}
/* Undoes a push_nested_class call. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fa73d67..e8d8acf 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2477,6 +2477,10 @@ struct lang_decl GTY(())
(TREE_CODE (TYPE) == BOOLEAN_TYPE \
|| TREE_CODE (TYPE) == INTEGER_TYPE)
+/* Returns true if TYPE is an integral or enumeration name. */
+#define INTEGRAL_OR_ENUMERATION_TYPE_P(TYPE) \
+ (CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == ENUMERAL_TYPE)
+
/* [basic.fundamental]
Integral and floating types are collectively called arithmetic
@@ -3642,9 +3646,9 @@ extern void finish_struct_1 (tree);
extern int resolves_to_fixed_type_p (tree, int *);
extern void init_class_processing (void);
extern int is_empty_class (tree);
-extern void pushclass (tree, int);
+extern void pushclass (tree, bool);
extern void popclass (void);
-extern void push_nested_class (tree, int);
+extern void push_nested_class (tree);
extern void pop_nested_class (void);
extern int current_lang_depth (void);
extern void push_lang_context (tree);
@@ -3854,7 +3858,6 @@ extern void check_member_template (tree);
extern tree grokfield (tree, tree, tree, tree, tree);
extern tree grokbitfield (tree, tree, tree);
extern tree groktypefield (tree, tree);
-extern tree grokoptypename (tree, tree, tree);
extern void cplus_decl_attributes (tree *, tree, int);
extern tree constructor_name_full (tree);
extern tree constructor_name (tree);
@@ -4009,7 +4012,6 @@ extern void cxx_init_options (void);
/* in method.c */
extern void init_method (void);
extern void set_mangled_name_for_decl (tree);
-extern tree build_opfncall (enum tree_code, int, tree, tree, tree);
extern tree hack_identifier (tree, tree);
extern tree make_thunk (tree, bool, tree, tree);
extern void finish_thunk (tree);
@@ -4026,10 +4028,6 @@ extern bool maybe_clone_body (tree);
/* in pt.c */
extern void check_template_shadow (tree);
extern tree get_innermost_template_args (tree, int);
-extern tree tsubst (tree, tree, tsubst_flags_t, tree);
-extern tree tsubst_expr (tree, tree, tsubst_flags_t, tree);
-extern tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
-extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree);
extern void maybe_begin_member_template_processing (tree);
extern void maybe_end_member_template_processing (void);
extern tree finish_member_template_decl (tree);
@@ -4086,6 +4084,9 @@ extern bool dependent_type_p (tree);
extern bool dependent_template_arg_p (tree);
extern bool dependent_template_p (tree);
extern bool type_dependent_expression_p (tree);
+extern bool value_dependent_expression_p (tree);
+extern tree resolve_typename_type (tree, bool);
+extern tree resolve_typename_type_in_current_instantiation (tree);
/* in repo.c */
extern void repo_template_used (tree);
@@ -4226,7 +4227,6 @@ extern tree finish_unary_op_expr (enum tree_code, tree);
extern tree finish_compound_literal (tree, tree);
extern tree finish_fname (tree);
extern int begin_function_definition (tree, tree, tree);
-extern tree begin_constructor_declarator (tree, tree);
extern tree finish_declarator (tree, tree, tree, tree, int);
extern void finish_translation_unit (void);
extern tree finish_template_type_parm (tree, tree);
@@ -4238,7 +4238,6 @@ extern void finish_default_args (void);
extern tree finish_member_class_template (tree);
extern void finish_template_decl (tree);
extern tree finish_template_type (tree, tree, int);
-extern void enter_scope_of (tree);
extern tree finish_base_specifier (tree, tree);
extern void finish_member_declaration (tree);
extern void check_multiple_declarators (void);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d2b7527..9078da6 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -105,7 +105,6 @@ static tree record_builtin_java_type (const char *, int);
static const char *tag_name (enum tag_types code);
static void find_class_binding_level (void);
static struct cp_binding_level *innermost_nonclass_level (void);
-static void warn_about_implicit_typename_lookup (tree, tree);
static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
static int walk_globals_r (tree, void*);
static int walk_vtables_r (tree, void*);
@@ -5072,8 +5071,6 @@ finish_case_label (tree low_value, tree high_value)
cond = TREE_VALUE (cond);
r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
- if (r == error_mark_node)
- r = NULL_TREE;
check_switch_goto (switch_stack->level);
@@ -5785,30 +5782,6 @@ qualify_lookup (tree val, int flags)
return val;
}
-/* Any other BINDING overrides an implicit TYPENAME. Warn about
- that. */
-
-static void
-warn_about_implicit_typename_lookup (tree typename, tree binding)
-{
- tree subtype = TREE_TYPE (TREE_TYPE (typename));
- tree name = DECL_NAME (typename);
-
- if (! (TREE_CODE (binding) == TEMPLATE_DECL
- && CLASSTYPE_TEMPLATE_INFO (subtype)
- && CLASSTYPE_TI_TEMPLATE (subtype) == binding)
- && ! (TREE_CODE (binding) == TYPE_DECL
- && same_type_p (TREE_TYPE (binding), subtype)))
- {
- warning ("lookup of `%D' finds `%#D'",
- name, binding);
- warning (" instead of `%D' from dependent base class",
- typename);
- warning (" (use `typename %T::%D' if that's what you meant)",
- constructor_name (current_class_type), name);
- }
-}
-
/* Look up NAME (an IDENTIFIER_NODE) in SCOPE (either a NAMESPACE_DECL
or a class TYPE). If IS_TYPE_P is TRUE, then ignore non-type
bindings.
@@ -7078,7 +7051,7 @@ start_decl (tree declarator,
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
- push_nested_class (context, 2);
+ push_nested_class (context);
if (TREE_CODE (decl) == VAR_DECL)
{
@@ -9086,9 +9059,11 @@ grokfndecl (tree ctype,
/* Attempt to merge the declarations. This can fail, in
the case of some invalid specialization declarations. */
+ push_scope (ctype);
if (!duplicate_decls (decl, old_decl))
error ("no `%#D' member function declared in class `%T'",
decl, ctype);
+ pop_scope (ctype);
return old_decl;
}
}
@@ -11055,35 +11030,6 @@ grokdeclarator (tree declarator,
attrlist = &returned_attrs;
}
- /* Resolve any TYPENAME_TYPEs from the decl-specifier-seq that refer
- to ctype. They couldn't be resolved earlier because we hadn't
- pushed into the class yet.
-
- For example, consider:
-
- template <typename T>
- struct S {
- typedef T X;
- X f();
- };
-
- template <typename T>
- typename S<T>::X f() {}
-
- When parsing the decl-specifier-seq for the definition of `f',
- we construct a TYPENAME_TYPE for `S<T>::X'. By substituting
- here, we resolve it to the correct type. */
- if (scope && CLASS_TYPE_P (scope)
- && current_template_parms
- && uses_template_parms (scope))
- {
- tree args = current_template_args ();
- push_scope (scope);
- type = tsubst (type, args, tf_error | tf_warning,
- NULL_TREE);
- pop_scope (scope);
- }
-
/* Now TYPE has the actual type. */
/* Did array size calculations overflow? */
@@ -13470,9 +13416,9 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
/* Set up current_class_type, and enter the scope of the class, if
appropriate. */
if (ctype)
- push_nested_class (ctype, 1);
+ push_nested_class (ctype);
else if (DECL_STATIC_FUNCTION_P (decl1))
- push_nested_class (DECL_CONTEXT (decl1), 2);
+ push_nested_class (DECL_CONTEXT (decl1));
/* Now that we have entered the scope of the class, we must restore
the bindings for any template parameters surrounding DECL1, if it
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 4401dcc..63240dd 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -423,8 +423,8 @@ grok_array_decl (tree array_expr, tree index_exp)
/* If they have an `operator[]', use that. */
if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
- return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
- array_expr, index_exp, NULL_TREE);
+ return 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
@@ -685,6 +685,7 @@ check_classfn (tree ctype, tree function)
bool is_conv_op;
const char *format = NULL;
+ push_scope (ctype);
for (fndecls = TREE_VEC_ELT (methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
@@ -713,8 +714,11 @@ check_classfn (tree ctype, tree function)
&& (!DECL_TEMPLATE_SPECIALIZATION (function)
|| (DECL_TI_TEMPLATE (function)
== DECL_TI_TEMPLATE (fndecl))))
- return fndecl;
+ break;
}
+ pop_scope (ctype);
+ if (fndecls)
+ return OVL_CURRENT (fndecls);
error ("prototype for `%#D' does not match any in class `%T'",
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
@@ -1071,30 +1075,6 @@ grokbitfield (tree declarator, tree declspecs, tree width)
return value;
}
-/* Convert a conversion operator name to an identifier. SCOPE is the
- scope of the conversion operator, if explicit. */
-
-tree
-grokoptypename (tree declspecs, tree declarator, tree scope)
-{
- tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL);
-
- /* Resolve any TYPENAME_TYPEs that refer to SCOPE, before mangling
- the name, so that we mangle the right thing. */
- if (scope && current_template_parms
- && uses_template_parms (t)
- && uses_template_parms (scope))
- {
- tree args = current_template_args ();
-
- push_scope (scope);
- t = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
- pop_scope (scope);
- }
-
- return mangle_conv_op_name_for_type (t);
-}
-
/* When a function is declared with an initializer,
do the right thing. Currently, there are two possibilities:
@@ -3749,7 +3729,7 @@ push_scope (tree t)
if (TREE_CODE (t) == NAMESPACE_DECL)
push_decl_namespace (t);
else if CLASS_TYPE_P (t)
- push_nested_class (t, 2);
+ push_nested_class (t);
}
/* Leave scope pushed by push_scope. */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index d53943f..9fe4167 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -454,6 +454,7 @@ dump_type (t, flags)
break;
}
case TYPENAME_TYPE:
+ dump_qualifiers (t, after);
output_add_string (scratch_buffer, "typename ");
dump_typename (t, flags);
break;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 493f9b8..c2661e8 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1511,8 +1511,8 @@ build_member_call (type, name, parmlist)
return error_mark_node;
}
if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl,
- parmlist, NULL_TREE);
+ return build_new_op (CALL_EXPR, LOOKUP_NORMAL, decl,
+ parmlist, NULL_TREE);
return build_function_call (decl, parmlist);
}
else
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 883a81f..a60b75f 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -85,36 +85,6 @@ set_mangled_name_for_decl (tree decl)
}
-/* Given a tree_code CODE, and some arguments (at least one),
- attempt to use an overloaded operator on the arguments.
-
- For unary operators, only the first argument need be checked.
- For binary operators, both arguments may need to be checked.
-
- Member functions can convert class references to class pointers,
- for one-level deep indirection. More than that is not supported.
- Operators [](), ()(), and ->() must be member functions.
-
- We call function call building calls with LOOKUP_COMPLAIN if they
- are our only hope. This is true when we see a vanilla operator
- applied to something of aggregate type. If this fails, we are free
- to return `error_mark_node', because we will have reported the
- error.
-
- Operators NEW and DELETE overload in funny ways: operator new takes
- a single `size' parameter, and operator delete takes a pointer to the
- storage being deleted. When overloading these operators, success is
- assumed. If there is a failure, report an error message and return
- `error_mark_node'. */
-
-/* NOSTRICT */
-tree
-build_opfncall (enum tree_code code, int flags,
- tree xarg1, tree xarg2, tree arg3)
-{
- return build_new_op (code, flags, xarg1, xarg2, arg3);
-}
-
/* This function takes an identifier, ID, and attempts to figure out what
it means. There are a number of possible scenarios, presented in increasing
order of hair:
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index da9a92f..fab1ef4 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1275,9 +1275,18 @@ typedef struct cp_parser GTY(())
/* TRUE if we are parsing an integral constant-expression. See
[expr.const] for a precise definition. */
- /* FIXME: Need to implement code that checks this flag. */
bool constant_expression_p;
+ /* TRUE if we are parsing an integral constant-expression -- but a
+ non-constant expression should be permitted as well. This flag
+ is used when parsing an array bound so that GNU variable-length
+ arrays are tolerated. */
+ bool allow_non_constant_expression_p;
+
+ /* TRUE if ALLOW_NON_CONSTANT_EXPRESSION_P is TRUE and something has
+ been seen that makes the expression non-constant. */
+ bool non_constant_expression_p;
+
/* TRUE if local variable names and `this' are forbidden in the
current context. */
bool local_variables_forbidden_p;
@@ -1422,7 +1431,7 @@ static enum tree_code cp_parser_assignment_operator_opt
static tree cp_parser_expression
(cp_parser *);
static tree cp_parser_constant_expression
- (cp_parser *);
+ (cp_parser *, bool, bool *);
/* Statements [gram.stmt.stmt] */
@@ -1658,8 +1667,6 @@ static tree cp_parser_lookup_name
(cp_parser *, tree, bool, bool, bool, bool);
static tree cp_parser_lookup_name_simple
(cp_parser *, tree);
-static tree cp_parser_resolve_typename_type
- (cp_parser *, tree);
static tree cp_parser_maybe_treat_template_as_class
(tree, bool);
static bool cp_parser_check_declarator_template_parameters
@@ -1728,6 +1735,10 @@ static bool cp_parser_simulate_error
(cp_parser *);
static void cp_parser_check_type_definition
(cp_parser *);
+static tree cp_parser_non_constant_expression
+ (const char *);
+static tree cp_parser_non_constant_id_expression
+ (tree);
static bool cp_parser_diagnose_invalid_type_name
(cp_parser *);
static bool cp_parser_skip_to_closing_parenthesis
@@ -1875,6 +1886,26 @@ cp_parser_check_type_definition (cp_parser* parser)
error ("%s", parser->type_definition_forbidden_message);
}
+/* Issue an eror message about the fact that THING appeared in a
+ constant-expression. Returns ERROR_MARK_NODE. */
+
+static tree
+cp_parser_non_constant_expression (const char *thing)
+{
+ error ("%s cannot appear in a constant-expression", thing);
+ return error_mark_node;
+}
+
+/* Issue an eror message about the fact that DECL appeared in a
+ constant-expression. Returns ERROR_MARK_NODE. */
+
+static tree
+cp_parser_non_constant_id_expression (tree decl)
+{
+ error ("`%D' cannot appear in a constant-expression", decl);
+ return error_mark_node;
+}
+
/* Check for a common situation where a type-name should be present,
but is not, and issue a sensible error message. Returns true if an
invalid type-name was detected. */
@@ -2182,6 +2213,8 @@ cp_parser_new (void)
/* We are not parsing a constant-expression. */
parser->constant_expression_p = false;
+ parser->allow_non_constant_expression_p = false;
+ parser->non_constant_expression_p = false;
/* Local variable names are not forbidden. */
parser->local_variables_forbidden_p = false;
@@ -2395,6 +2428,13 @@ cp_parser_primary_expression (cp_parser *parser,
error ("`this' may not be used in this context");
return error_mark_node;
}
+ /* Pointers cannot appear in constant-expressions. */
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression ("`this'");
+ parser->non_constant_expression_p = true;
+ }
return finish_this_expr ();
/* The `operator' keyword can be the beginning of an
@@ -2434,7 +2474,14 @@ cp_parser_primary_expression (cp_parser *parser,
type = cp_parser_type_id (parser);
/* Look for the closing `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-
+ /* Using `va_arg' in a constant-expression is not
+ allowed. */
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression ("`va_arg'");
+ parser->non_constant_expression_p = true;
+ }
return build_x_va_arg (expression, type);
}
@@ -2481,6 +2528,11 @@ cp_parser_primary_expression (cp_parser *parser,
{
if (TYPE_P (TREE_OPERAND (decl, 0)))
*qualifying_class = TREE_OPERAND (decl, 0);
+ /* Since this name was dependent, the expression isn't
+ constant -- yet. No error is issued because it
+ might be constant when things are instantiated. */
+ if (parser->constant_expression_p)
+ parser->non_constant_expression_p = true;
return decl;
}
/* Check to see if DECL is a local variable in a context
@@ -2704,6 +2756,11 @@ cp_parser_primary_expression (cp_parser *parser,
{
if (TYPE_P (parser->scope))
*qualifying_class = parser->scope;
+ /* Since this name was dependent, the expression isn't
+ constant -- yet. No error is issued because it
+ might be constant when things are instantiated. */
+ if (parser->constant_expression_p)
+ parser->non_constant_expression_p = true;
return build_nt (SCOPE_REF,
parser->scope,
id_expression);
@@ -2712,10 +2769,36 @@ cp_parser_primary_expression (cp_parser *parser,
we need. */
if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
return id_expression;
+ /* Since this name was dependent, the expression isn't
+ constant -- yet. No error is issued because it
+ might be constant when things are instantiated. */
+ if (parser->constant_expression_p)
+ parser->non_constant_expression_p = true;
/* Create a LOOKUP_EXPR for other unqualified names. */
return build_min_nt (LOOKUP_EXPR, id_expression);
}
+ /* Only certain kinds of names are allowed in constant
+ expression. Enumerators have already been handled
+ above. */
+ 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)))
+ /* Const variables or static data members of integral
+ or enumeration types initialized with constant
+ expressions. */
+ && !(TREE_CODE (decl) == VAR_DECL
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
+ && DECL_INITIAL (decl)
+ && TREE_CONSTANT (DECL_INITIAL (decl))))
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_id_expression (decl);
+ parser->non_constant_expression_p = true;
+ }
+
if (parser->scope)
{
decl = (adjust_result_of_qualified_name_lookup
@@ -3520,6 +3603,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
expression = cp_parser_expression (parser);
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ /* Only type conversions to integral or enumeration types
+ can be used in constant-expressions. */
+ if (parser->constant_expression_p
+ && !dependent_type_p (type)
+ && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return (cp_parser_non_constant_expression
+ ("a cast to a type other than an integral or "
+ "enumeration type"));
+ parser->non_constant_expression_p = true;
+ }
+
switch (keyword)
{
case RID_DYNCAST:
@@ -3645,32 +3741,32 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* If the functional-cast didn't work out, try a
compound-literal. */
- if (cp_parser_allow_gnu_extensions_p (parser))
+ if (cp_parser_allow_gnu_extensions_p (parser)
+ && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
tree initializer_list = NULL_TREE;
cp_parser_parse_tentatively (parser);
- /* Look for the `('. */
- if (cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ /* Consume the `('. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the type. */
+ type = cp_parser_type_id (parser);
+ /* Look for the `)'. */
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ /* Look for the `{'. */
+ cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+ /* If things aren't going well, there's no need to
+ keep going. */
+ if (!cp_parser_error_occurred (parser))
{
- type = cp_parser_type_id (parser);
- /* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
- /* Look for the `{'. */
- cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
- /* If things aren't going well, there's no need to
- keep going. */
- if (!cp_parser_error_occurred (parser))
- {
- /* Parse the initializer-list. */
- initializer_list
- = cp_parser_initializer_list (parser);
- /* Allow a trailing `,'. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- cp_lexer_consume_token (parser->lexer);
- /* Look for the final `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
- }
+ /* Parse the initializer-list. */
+ initializer_list
+ = cp_parser_initializer_list (parser);
+ /* Allow a trailing `,'. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ /* Look for the final `}'. */
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
}
/* If that worked, we're definitely looking at a
compound-literal expression. */
@@ -3806,6 +3902,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
args = NULL_TREE;
/* Look for the closing `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ /* Function calls are not permitted in
+ constant-expressions. */
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression ("a function call");
+ parser->non_constant_expression_p = true;
+ }
if (idk == CP_PARSER_ID_KIND_UNQUALIFIED
&& (is_overloaded_fn (postfix_expression)
@@ -4029,6 +4133,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* postfix-expression ++ */
/* Consume the `++' token. */
cp_lexer_consume_token (parser->lexer);
+ /* Increments may not appear in constant-expressions. */
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression ("an increment");
+ parser->non_constant_expression_p = true;
+ }
/* Generate a reprsentation for the complete expression. */
postfix_expression
= finish_increment_expr (postfix_expression,
@@ -4040,6 +4151,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* postfix-expression -- */
/* Consume the `--' token. */
cp_lexer_consume_token (parser->lexer);
+ /* Decrements may not appear in constant-expressions. */
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression ("a decrement");
+ parser->non_constant_expression_p = true;
+ }
/* Generate a reprsentation for the complete expression. */
postfix_expression
= finish_increment_expr (postfix_expression,
@@ -4341,11 +4459,20 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
case ADDR_EXPR:
return build_x_unary_op (ADDR_EXPR, cast_expression);
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression (PREINCREMENT_EXPR
+ ? "an increment"
+ : "a decrement");
+ parser->non_constant_expression_p = true;
+ }
+ /* Fall through. */
case CONVERT_EXPR:
case NEGATE_EXPR:
case TRUTH_NOT_EXPR:
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
return finish_unary_op_expr (unary_operator, cast_expression);
case BIT_NOT_EXPR:
@@ -4597,7 +4724,10 @@ cp_parser_direct_new_declarator (cp_parser* parser)
}
/* But all the other expressions must be. */
else
- expression = cp_parser_constant_expression (parser);
+ expression
+ = cp_parser_constant_expression (parser,
+ /*allow_non_constant=*/false,
+ NULL);
/* Look for the closing `]'. */
cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
@@ -4766,7 +4896,19 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
&& !VOID_TYPE_P (type)
&& current_lang_name != lang_name_c)
warning ("use of old-style cast");
-
+
+ /* Only type conversions to integral or enumeration types
+ can be used in constant-expressions. */
+ if (parser->constant_expression_p
+ && !dependent_type_p (type)
+ && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return (cp_parser_non_constant_expression
+ ("a casts to a type other than an integral or "
+ "enumeration type"));
+ parser->non_constant_expression_p = true;
+ }
/* Perform the cast. */
expr = build_c_cast (type, expr);
return expr;
@@ -5176,6 +5318,14 @@ cp_parser_assignment_expression (cp_parser* parser)
/* Parse the right-hand side of the assignment. */
rhs = cp_parser_assignment_expression (parser);
+ /* An assignment may not appear in a
+ constant-expression. */
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression ("an assignment");
+ parser->non_constant_expression_p = true;
+ }
/* Build the asignment expression. */
expr = build_x_modify_expr (expr,
assignment_operator,
@@ -5334,7 +5484,16 @@ cp_parser_expression (cp_parser* parser)
necessary. We built up the list in reverse order, so we must
straighten it out here. */
if (saw_comma_p)
- expression = build_x_compound_expr (nreverse (expression));
+ {
+ /* 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");
+ parser->non_constant_expression_p = true;
+ }
+ expression = build_x_compound_expr (nreverse (expression));
+ }
return expression;
}
@@ -5342,12 +5501,20 @@ cp_parser_expression (cp_parser* parser)
/* Parse a constant-expression.
constant-expression:
- conditional-expression */
+ 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. */
static tree
-cp_parser_constant_expression (cp_parser* parser)
+cp_parser_constant_expression (cp_parser* parser,
+ bool allow_non_constant_p,
+ bool *non_constant_p)
{
bool saved_constant_expression_p;
+ bool saved_allow_non_constant_expression_p;
+ bool saved_non_constant_expression_p;
tree expression;
/* It might seem that we could simply parse the
@@ -5367,14 +5534,24 @@ cp_parser_constant_expression (cp_parser* parser)
constant-expression. However, GCC's constant-folding machinery
will fold this operation to an INTEGER_CST for `3'. */
- /* Save the old setting of CONSTANT_EXPRESSION_P. */
+ /* Save the old settings. */
saved_constant_expression_p = parser->constant_expression_p;
+ saved_allow_non_constant_expression_p
+ = parser->allow_non_constant_expression_p;
+ saved_non_constant_expression_p = parser->non_constant_expression_p;
/* We are now parsing a constant-expression. */
parser->constant_expression_p = true;
+ parser->allow_non_constant_expression_p = allow_non_constant_p;
+ parser->non_constant_expression_p = false;
/* Parse the conditional-expression. */
expression = cp_parser_conditional_expression (parser);
- /* Restore the old setting of CONSTANT_EXPRESSION_P. */
+ /* Restore the old settings. */
parser->constant_expression_p = saved_constant_expression_p;
+ parser->allow_non_constant_expression_p
+ = saved_allow_non_constant_expression_p;
+ if (allow_non_constant_p)
+ *non_constant_p = parser->non_constant_expression_p;
+ parser->non_constant_expression_p = saved_non_constant_expression_p;
return expression;
}
@@ -5517,7 +5694,9 @@ cp_parser_labeled_statement (cp_parser* parser)
/* Consume the `case' token. */
cp_lexer_consume_token (parser->lexer);
/* Parse the constant-expression. */
- expr = cp_parser_constant_expression (parser);
+ expr = cp_parser_constant_expression (parser,
+ /*allow_non_constant=*/false,
+ NULL);
/* Create the label. */
statement = finish_case_label (expr, NULL_TREE);
}
@@ -8875,7 +9054,9 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
/* Consume the `=' token. */
cp_lexer_consume_token (parser->lexer);
/* Parse the value. */
- value = cp_parser_constant_expression (parser);
+ value = cp_parser_constant_expression (parser,
+ /*allow_non_constant=*/false,
+ NULL);
}
else
value = NULL_TREE;
@@ -9870,7 +10051,34 @@ cp_parser_direct_declarator (cp_parser* parser,
/* If the next token is `]', then there is no
constant-expression. */
if (token->type != CPP_CLOSE_SQUARE)
- bounds = cp_parser_constant_expression (parser);
+ {
+ bool non_constant_p;
+
+ bounds
+ = 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 = build_expr_from_tree (bounds);
+ processing_template_decl = saved_processing_template_decl;
+ }
+ }
else
bounds = NULL_TREE;
/* Look for the closing `]'. */
@@ -9924,11 +10132,14 @@ cp_parser_direct_declarator (cp_parser* parser,
is no harm in resolving the types here. */
if (TREE_CODE (scope) == TYPENAME_TYPE)
{
+ tree type;
+
/* Resolve the TYPENAME_TYPE. */
- scope = cp_parser_resolve_typename_type (parser, scope);
+ type = resolve_typename_type (scope,
+ /*only_current_p=*/false);
/* If that failed, the declarator is invalid. */
- if (scope == error_mark_node)
- return error_mark_node;
+ if (type != error_mark_node)
+ scope = type;
/* Build a new DECLARATOR. */
declarator = build_nt (SCOPE_REF,
scope,
@@ -11549,16 +11760,22 @@ cp_parser_class_head (cp_parser* parser,
/* Given:
template <typename T> struct S { struct T };
- template <typename T> struct S::T { };
+ template <typename T> struct S<T>::T { };
we will get a TYPENAME_TYPE when processing the definition of
`S::T'. We need to resolve it to the actual type before we
try to define it. */
if (TREE_CODE (TREE_TYPE (type)) == TYPENAME_TYPE)
{
- type = cp_parser_resolve_typename_type (parser, TREE_TYPE (type));
- if (type != error_mark_node)
- type = TYPE_NAME (type);
+ class_type = resolve_typename_type (TREE_TYPE (type),
+ /*only_current_p=*/false);
+ if (class_type != error_mark_node)
+ type = TYPE_NAME (class_type);
+ else
+ {
+ cp_parser_error (parser, "could not resolve typename type");
+ type = error_mark_node;
+ }
}
maybe_process_partial_specialization (TREE_TYPE (type));
@@ -11889,7 +12106,10 @@ cp_parser_member_declaration (cp_parser* parser)
/* Consume the `:' token. */
cp_lexer_consume_token (parser->lexer);
/* Get the width of the bitfield. */
- width = cp_parser_constant_expression (parser);
+ width
+ = cp_parser_constant_expression (parser,
+ /*allow_non_constant=*/false,
+ NULL);
/* Look for attributes that apply to the bitfield. */
attributes = cp_parser_attributes_opt (parser);
@@ -12112,7 +12332,9 @@ cp_parser_constant_initializer (cp_parser* parser)
return error_mark_node;
}
- return cp_parser_constant_expression (parser);
+ return cp_parser_constant_expression (parser,
+ /*allow_non_constant=*/false,
+ NULL);
}
/* Derived classes [gram.class.derived] */
@@ -13148,58 +13370,6 @@ cp_parser_lookup_name_simple (cp_parser* parser, tree name)
/*check_dependency=*/true);
}
-/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
- TYPENAME_TYPE corresponds. Note that this function peers inside
- uninstantiated templates and therefore should be used only in
- extremely limited situations. */
-
-static tree
-cp_parser_resolve_typename_type (cp_parser* parser, tree type)
-{
- tree scope;
- tree name;
- tree decl;
-
- my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE,
- 20010702);
-
- scope = TYPE_CONTEXT (type);
- name = TYPE_IDENTIFIER (type);
-
- /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
- it first before we can figure out what NAME refers to. */
- if (TREE_CODE (scope) == TYPENAME_TYPE)
- scope = cp_parser_resolve_typename_type (parser, scope);
- /* If we don't know what SCOPE refers to, then we cannot resolve the
- TYPENAME_TYPE. */
- if (scope == error_mark_node || TREE_CODE (scope) == TYPENAME_TYPE)
- return error_mark_node;
- /* If the SCOPE is a template type parameter, we have no way of
- resolving the name. */
- if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM)
- return type;
- /* Enter the SCOPE so that name lookup will be resolved as if we
- were in the class definition. In particular, SCOPE will no
- longer be considered a dependent type. */
- push_scope (scope);
- /* Look up the declaration. */
- decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/1);
- /* If all went well, we got a TYPE_DECL for a non-typename. */
- if (!decl
- || TREE_CODE (decl) != TYPE_DECL
- || TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
- {
- cp_parser_error (parser, "could not resolve typename type");
- type = error_mark_node;
- }
- else
- type = TREE_TYPE (decl);
- /* Leave the SCOPE. */
- pop_scope (scope);
-
- return type;
-}
-
/* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
the current context, return the TYPE_DECL. If TAG_NAME_P is
true, the DECL indicates the class being defined in a class-head,
@@ -13547,7 +13717,15 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
{
type = TREE_TYPE (type_decl);
if (TREE_CODE (type) == TYPENAME_TYPE)
- type = cp_parser_resolve_typename_type (parser, type);
+ {
+ type = resolve_typename_type (type,
+ /*only_current_p=*/false);
+ if (type == error_mark_node)
+ {
+ cp_parser_abort_tentative_parse (parser);
+ return false;
+ }
+ }
push_scope (type);
}
/* Look for the type-specifier. */
@@ -13978,7 +14156,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
parser->local_variables_forbidden_p = true;
/* Parse the assignment-expression. */
if (DECL_CONTEXT (fn))
- push_nested_class (DECL_CONTEXT (fn), 1);
+ push_nested_class (DECL_CONTEXT (fn));
TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
if (DECL_CONTEXT (fn))
pop_nested_class ();
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b3b8106..2429f7f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -171,8 +171,11 @@ static void copy_default_args_to_explicit_spec PARAMS ((tree));
static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
static int eq_local_specializations (const void *, const void *);
static tree template_for_substitution (tree);
-static bool value_dependent_expression_p (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);
+static tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@@ -215,7 +218,7 @@ push_access_scope_real (t, args, context)
if (!context)
context = DECL_CONTEXT (t);
if (context && TYPE_P (context))
- push_nested_class (context, 2);
+ push_nested_class (context);
else
push_to_top_level ();
@@ -5043,7 +5046,7 @@ tsubst_friend_class (friend_tmpl, args)
if (TREE_CODE (context) == NAMESPACE_DECL)
push_nested_namespace (context);
else
- push_nested_class (tsubst (context, args, tf_none, NULL_TREE), 2);
+ push_nested_class (tsubst (context, args, tf_none, NULL_TREE));
}
/* First, we look for a class template. */
@@ -5328,7 +5331,7 @@ instantiate_class_template (type)
correctly. This is precisely analogous to what we do in
begin_class_definition when defining an ordinary non-template
class. */
- pushclass (type, 1);
+ pushclass (type, true);
/* Now members are processed in the order of declaration. */
for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member))
@@ -6467,7 +6470,7 @@ tsubst_call_declarator_parms (parms, args, complain, in_decl)
This function is used for dealing with types, decls and the like;
for expressions, use tsubst_expr or tsubst_copy. */
-tree
+static tree
tsubst (t, args, complain, in_decl)
tree t, args;
tsubst_flags_t complain;
@@ -7103,7 +7106,7 @@ tsubst (t, args, complain, in_decl)
template parms; to finish processing the resultant expression, use
tsubst_expr. */
-tree
+static tree
tsubst_copy (t, args, complain, in_decl)
tree t, args;
tsubst_flags_t complain;
@@ -7505,7 +7508,7 @@ tsubst_copy (t, args, complain, in_decl)
/* Like tsubst_copy for expressions, etc. but also does semantic
processing. */
-tree
+static tree
tsubst_expr (t, args, complain, in_decl)
tree t, args;
tsubst_flags_t complain;
@@ -7832,7 +7835,7 @@ tsubst_expr (t, args, complain, in_decl)
/* Like tsubst but deals with expressions and performs semantic
analysis. */
-tree
+static tree
tsubst_copy_and_build (t, args, complain, in_decl)
tree t, args;
tsubst_flags_t complain;
@@ -11314,15 +11317,16 @@ dependent_type_p (type)
/* Returns TRUE if the EXPRESSION is value-dependent. */
-static bool
+bool
value_dependent_expression_p (tree expression)
{
if (!processing_template_decl)
return false;
/* A name declared with a dependent type. */
- if (DECL_P (expression)
- && dependent_type_p (TREE_TYPE (expression)))
+ if (TREE_CODE (expression) == LOOKUP_EXPR
+ || (DECL_P (expression)
+ && dependent_type_p (TREE_TYPE (expression))))
return true;
/* A non-type template parameter. */
if ((TREE_CODE (expression) == CONST_DECL
@@ -11370,11 +11374,14 @@ value_dependent_expression_p (tree expression)
case 'e':
{
int i;
- for (i = 0;
- i < TREE_CODE_LENGTH (TREE_CODE (expression));
- ++i)
- if (value_dependent_expression_p
- (TREE_OPERAND (expression, i)))
+ for (i = 0; i < first_rtl_op (TREE_CODE (expression)); ++i)
+ /* In some cases, some of the operands may be missing.
+ (For example, in the case of PREDECREMENT_EXPR, the
+ amount to increment by may be missing.) That doesn't
+ make the expression dependent. */
+ if (TREE_OPERAND (expression, i)
+ && (value_dependent_expression_p
+ (TREE_OPERAND (expression, i))))
return true;
return false;
}
@@ -11478,4 +11485,88 @@ dependent_template_p (tree tmpl)
return false;
}
+/* 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
+ templates and therefore should be used only in extremely limited
+ situations. */
+
+tree
+resolve_typename_type (tree type, bool only_current_p)
+{
+ tree scope;
+ tree name;
+ tree decl;
+ int quals;
+
+ my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE,
+ 20010702);
+
+ scope = TYPE_CONTEXT (type);
+ name = TYPE_IDENTIFIER (type);
+
+ /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
+ it first before we can figure out what NAME refers to. */
+ if (TREE_CODE (scope) == TYPENAME_TYPE)
+ scope = resolve_typename_type (scope, only_current_p);
+ /* If we don't know what SCOPE refers to, then we cannot resolve the
+ TYPENAME_TYPE. */
+ if (scope == error_mark_node || TREE_CODE (scope) == TYPENAME_TYPE)
+ return error_mark_node;
+ /* If the SCOPE is a template type parameter, we have no way of
+ resolving the name. */
+ if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM)
+ return type;
+ /* If the SCOPE is not the current instantiation, there's no reason
+ to look inside it. */
+ if (only_current_p && !currently_open_class (scope))
+ return error_mark_node;
+ /* Enter the SCOPE so that name lookup will be resolved as if we
+ were in the class definition. In particular, SCOPE will no
+ longer be considered a dependent type. */
+ push_scope (scope);
+ /* Look up the declaration. */
+ decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/1);
+ /* Obtain the set of qualifiers applied to the TYPE. */
+ quals = cp_type_quals (type);
+ /* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
+ find a TEMPLATE_DECL. Otherwise, we want to find a TYPE_DECL. */
+ if (!decl)
+ type = error_mark_node;
+ else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == IDENTIFIER_NODE
+ && TREE_CODE (decl) == TYPE_DECL)
+ type = TREE_TYPE (decl);
+ else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_EXPR
+ && DECL_CLASS_TEMPLATE_P (decl))
+ {
+ tree tmpl;
+ tree args;
+ /* Obtain the template and the arguments. */
+ tmpl = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 0);
+ args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1);
+ /* Instantiate the template. */
+ type = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
+ /*entering_scope=*/0,
+ tf_error);
+ }
+ else
+ type = error_mark_node;
+ /* Qualify the resulting type. */
+ if (type != error_mark_node && quals)
+ type = cp_build_qualified_type (type, quals);
+ /* Leave the SCOPE. */
+ pop_scope (scope);
+
+ return type;
+}
+
+tree
+resolve_typename_type_in_current_instantiation (tree type)
+{
+ tree t;
+
+ t = resolve_typename_type (type, /*only_current_p=*/true);
+ return (t != error_mark_node) ? t : type;
+}
+
#include "gt-cp-pt.h"
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index fb6f25d..9c0b28b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1434,7 +1434,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
/* If the "function" is really an object of class type, it might
have an overloaded `operator ()'. */
tree result;
- result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
+ result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
if (result)
return result;
}
@@ -1665,19 +1665,6 @@ begin_function_definition (decl_specs, attributes, declarator)
return 1;
}
-/* Begin a constructor declarator of the form `SCOPE::NAME'. Returns
- a SCOPE_REF. */
-
-tree
-begin_constructor_declarator (scope, name)
- tree scope;
- tree name;
-{
- tree result = build_nt (SCOPE_REF, scope, name);
- enter_scope_of (result);
- return result;
-}
-
/* Finish an init-declarator. Returns a DECL. */
tree
@@ -1831,7 +1818,7 @@ begin_class_definition (t)
pushtag (TYPE_IDENTIFIER (t), t, 0);
}
maybe_process_partial_specialization (t);
- pushclass (t, 1);
+ pushclass (t, true);
TYPE_BEING_DEFINED (t) = 1;
TYPE_PACKED (t) = flag_pack_struct;
/* Reset the interface data, at the earliest possible
@@ -2044,34 +2031,6 @@ finish_template_type (name, args, entering_scope)
return decl;
}
-/* SR is a SCOPE_REF node. Enter the scope of SR, whether it is a
- namespace scope or a class scope. */
-
-void
-enter_scope_of (sr)
- tree sr;
-{
- tree scope = TREE_OPERAND (sr, 0);
-
- if (TREE_CODE (scope) == NAMESPACE_DECL)
- {
- push_decl_namespace (scope);
- TREE_COMPLEXITY (sr) = -1;
- }
- else if (scope != current_class_type)
- {
- if (TREE_CODE (scope) == TYPENAME_TYPE)
- {
- /* In a declarator for a template class member, the scope will
- get here as an implicit typename, a TYPENAME_TYPE with a type. */
- scope = TREE_TYPE (scope);
- TREE_OPERAND (sr, 0) = scope;
- }
- push_nested_class (scope, 3);
- TREE_COMPLEXITY (sr) = current_class_depth;
- }
-}
-
/* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.
Return a TREE_LIST containing the ACCESS_SPECIFIER and the
BASE_CLASS, or NULL_TREE if an error occurred. The
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 57d95ad..9d11262 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -946,6 +946,13 @@ comptypes (t1, t2, strict)
if (TYPE_PTRMEMFUNC_P (t2))
t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
+ /* TYPENAME_TYPEs should be resolved if the qualifying scope is the
+ current instantiation. */
+ if (TREE_CODE (t1) == TYPENAME_TYPE)
+ t1 = resolve_typename_type_in_current_instantiation (t1);
+ if (TREE_CODE (t2) == TYPENAME_TYPE)
+ t2 = resolve_typename_type_in_current_instantiation (t2);
+
/* Different classes of types can't be compatible. */
if (TREE_CODE (t1) != TREE_CODE (t2))
return 0;
@@ -2301,8 +2308,8 @@ build_x_indirect_ref (ptr, errorstring)
if (processing_template_decl)
return build_min_nt (INDIRECT_REF, ptr);
- rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
- NULL_TREE);
+ rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
+ NULL_TREE);
if (rval)
return rval;
return build_indirect_ref (ptr, errorstring);
@@ -2973,6 +2980,183 @@ build_x_binary_op (code, arg1, arg2)
return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
}
+#if 0
+
+tree
+build_template_expr (enum tree_code code, tree op0, tree op1, tree op2)
+{
+ tree type;
+
+ /* If any of the operands is erroneous the result is erroneous too. */
+ if (error_operand_p (op0)
+ || (op1 && error_operand_p (op1))
+ || (op2 && error_operand_p (op2)))
+ return error_mark_node;
+
+ if (dependent_type_p (TREE_TYPE (op0))
+ || (op1 && dependent_type_p (TREE_TYPE (op1)))
+ || (op2 && dependent_type_p (TREE_TYPE (op2))))
+ /* If at least one operand has a dependent type, we cannot
+ determine the type of the expression until instantiation time. */
+ type = NULL_TREE;
+ else
+ {
+ struct z_candidate *cand;
+ 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; ... }
+
+ 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 conditioanl
+ expressions. */
+ break;
+ case COMPOUND_EXPR:
+ type = op1_type;
+ break;
+ default:
+ abort ();
+ }
+ /* If the type of the expression could not be determined,
+ something is wrong. */
+ if (!type)
+ abort ();
+ /* If the type is erroneous, the expression is erroneous
+ too. */
+ if (type == error_mark_node)
+ return error_mark_node;
+ }
+ }
+
+ return build_min (code, type, op0, op1, op2, NULL_TREE);
+}
+
+#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:
@@ -4602,8 +4786,8 @@ build_x_compound_expr (list)
if (rest == NULL_TREE)
return build_compound_expr (list);
- result = build_opfncall (COMPOUND_EXPR, LOOKUP_NORMAL,
- TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
+ 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)));
@@ -5235,8 +5419,8 @@ build_modify_expr (lhs, modifycode, rhs)
/* Do the default thing */;
else
{
- result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
+ result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
+ lhs, rhs, make_node (NOP_EXPR));
if (result == NULL_TREE)
return error_mark_node;
return result;
@@ -5488,8 +5672,8 @@ build_x_modify_expr (lhs, modifycode, rhs)
if (modifycode != NOP_EXPR)
{
- tree rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
- make_node (modifycode));
+ tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
+ make_node (modifycode));
if (rval)
return rval;
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 0a5b4dc..c7dcb52 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1044,8 +1044,8 @@ build_x_arrow (datum)
if (IS_AGGR_TYPE (type))
{
- while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval,
- NULL_TREE, NULL_TREE)))
+ while ((rval = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, rval,
+ NULL_TREE, NULL_TREE)))
{
if (rval == error_mark_node)
return error_mark_node;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fc39840..8704a8d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-01-29 Mark Mitchell <mark@codesourcery.com>
+
+ * g++.dg/parser/constant1.C: New test.
+
2003-01-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/8591
diff --git a/gcc/testsuite/g++.dg/parse/constant1.C b/gcc/testsuite/g++.dg/parse/constant1.C
new file mode 100644
index 0000000..0a88928
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/constant1.C
@@ -0,0 +1,13 @@
+void f () {
+ switch (0) {
+ case (3, 0): // { dg-error "" }
+ break;
+ }
+}
+
+int g ();
+
+struct S {
+ int i : (false ? g () : 1); // { dg-error "" }
+};
+