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
This commit is contained in:
parent
825db093df
commit
14d22dd667
20 changed files with 795 additions and 359 deletions
|
@ -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.
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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().
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -84,36 +84,6 @@ set_mangled_name_for_decl (tree decl)
|
|||
mangle_decl (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
|
||||
|
|
380
gcc/cp/parser.c
380
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 ();
|
||||
|
|
123
gcc/cp/pt.c
123
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"
|
||||
|
|
|
@ -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
|
||||
|
|
200
gcc/cp/typeck.c
200
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
13
gcc/testsuite/g++.dg/parse/constant1.C
Normal file
13
gcc/testsuite/g++.dg/parse/constant1.C
Normal file
|
@ -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 "" }
|
||||
};
|
||||
|
|
@ -1,3 +1,15 @@
|
|||
2003-01-29 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2003-01-28 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
PR c++/9433
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// The template and inlines for the -*- C++ -*- numeric_limits classes.
|
||||
|
||||
// Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
// Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
|
@ -893,10 +893,8 @@ namespace std
|
|||
static const int max_exponent = __FLT_MAX_EXP__;
|
||||
static const int max_exponent10 = __FLT_MAX_10_EXP__;
|
||||
|
||||
static const bool has_infinity
|
||||
= __builtin_huge_valf () / 2 == __builtin_huge_valf ();
|
||||
static const bool has_quiet_NaN
|
||||
= __builtin_nanf ("") != __builtin_nanf ("");
|
||||
static const bool has_infinity = __FLT_HAS_INFINITY__;
|
||||
static const bool has_quiet_NaN = __FLT_HAS_QUIET_NAN__;
|
||||
static const bool has_signaling_NaN = has_quiet_NaN;
|
||||
static const float_denorm_style has_denorm
|
||||
= __FLT_DENORM_MIN__ ? denorm_present : denorm_absent;
|
||||
|
@ -951,10 +949,8 @@ namespace std
|
|||
static const int max_exponent = __DBL_MAX_EXP__;
|
||||
static const int max_exponent10 = __DBL_MAX_10_EXP__;
|
||||
|
||||
static const bool has_infinity
|
||||
= __builtin_huge_val () / 2 == __builtin_huge_val ();
|
||||
static const bool has_quiet_NaN
|
||||
= __builtin_nan ("") != __builtin_nan ("");
|
||||
static const bool has_infinity = __DBL_HAS_INFINITY__;
|
||||
static const bool has_quiet_NaN = __DBL_HAS_QUIET_NAN__;
|
||||
static const bool has_signaling_NaN = has_quiet_NaN;
|
||||
static const float_denorm_style has_denorm
|
||||
= __DBL_DENORM_MIN__ ? denorm_present : denorm_absent;
|
||||
|
@ -1009,10 +1005,8 @@ namespace std
|
|||
static const int max_exponent = __LDBL_MAX_EXP__;
|
||||
static const int max_exponent10 = __LDBL_MAX_10_EXP__;
|
||||
|
||||
static const bool has_infinity
|
||||
= __builtin_huge_vall () / 2 == __builtin_huge_vall ();
|
||||
static const bool has_quiet_NaN
|
||||
= __builtin_nanl ("") != __builtin_nanl ("");
|
||||
static const bool has_infinity = __LDBL_HAS_INFINITY__;
|
||||
static const bool has_quiet_NaN = __LDBL_HAS_QUIET_NAN__;
|
||||
static const bool has_signaling_NaN = has_quiet_NaN;
|
||||
static const float_denorm_style has_denorm
|
||||
= __LDBL_DENORM_MIN__ ? denorm_present : denorm_absent;
|
||||
|
|
Loading…
Add table
Reference in a new issue