cp-tree.h (empty_except_spec): New global var.
* cp-tree.h (empty_except_spec): New global var. (compexcepttypes): Remove prototype. (comp_except_specs): Prototype new global function. (add_exception_specifier): Prototype new global function. * decl.c (empty_except_spec): Define new global var. (duplicate_decls): Use comp_except_specs, reword error message. (init_decl_processing): Initialize empty_except_spec. Adjust build_exception_variant calls. * parse.y (exception_specification_opt): Use empty_except_spec. (ansi_raise_identifier): Call check_for_new_type. (ansi_raise_identifiers): Use add_exception_specifier. * pt.c (tsubst): Use add_exception_specifier to build exception specifier. * search.c (check_final_overrider): New static function, broken out of get_matching_virtual. Check throw specifiers, reword diagnostics. (get_matching_virtual): Use check_final_overrider. * tree.c (build_exception_variant): Use comp_except_specs. * typeck.c (compexcepttypes): Remove. (comp_except_types): New static function, helper for comp_except_specs. Compare two types as exception specifiers. (comp_except_specs): New global function, compare two exception specifiers. (comptypes): Adjust for comp_except_specs. * typeck2.c (add_exception_specifier): New global function. * class.c (check_for_override): Reword error message. From-SVN: r28494
This commit is contained in:
parent
bc3c01c507
commit
4cc1d46201
|
@ -1,3 +1,33 @@
|
||||||
|
1999-08-04 Nathan Sidwell <nathan@acm.org>
|
||||||
|
|
||||||
|
* cp-tree.h (empty_except_spec): New global var.
|
||||||
|
(compexcepttypes): Remove prototype.
|
||||||
|
(comp_except_specs): Prototype new global function.
|
||||||
|
(add_exception_specifier): Prototype new global function.
|
||||||
|
* decl.c (empty_except_spec): Define new global var.
|
||||||
|
(duplicate_decls): Use comp_except_specs, reword error message.
|
||||||
|
(init_decl_processing): Initialize empty_except_spec.
|
||||||
|
Adjust build_exception_variant calls.
|
||||||
|
* parse.y (exception_specification_opt): Use empty_except_spec.
|
||||||
|
(ansi_raise_identifier): Call check_for_new_type.
|
||||||
|
(ansi_raise_identifiers): Use add_exception_specifier.
|
||||||
|
* pt.c (tsubst): Use add_exception_specifier to build exception
|
||||||
|
specifier.
|
||||||
|
* search.c (check_final_overrider): New static function, broken
|
||||||
|
out of get_matching_virtual. Check throw specifiers, reword
|
||||||
|
diagnostics.
|
||||||
|
(get_matching_virtual): Use check_final_overrider.
|
||||||
|
* tree.c (build_exception_variant): Use comp_except_specs.
|
||||||
|
* typeck.c (compexcepttypes): Remove.
|
||||||
|
(comp_except_types): New static function, helper for
|
||||||
|
comp_except_specs. Compare two types as exception specifiers.
|
||||||
|
(comp_except_specs): New global function, compare two exception
|
||||||
|
specifiers.
|
||||||
|
(comptypes): Adjust for comp_except_specs.
|
||||||
|
* typeck2.c (add_exception_specifier): New global function.
|
||||||
|
|
||||||
|
* class.c (check_for_override): Reword error message.
|
||||||
|
|
||||||
1999-08-03 Nathan Sidwell <nathan@acm.org>
|
1999-08-03 Nathan Sidwell <nathan@acm.org>
|
||||||
|
|
||||||
* call.c (convert_arg_to_ellipsis): Use pod_type_p.
|
* call.c (convert_arg_to_ellipsis): Use pod_type_p.
|
||||||
|
|
|
@ -2977,9 +2977,8 @@ check_for_override (decl, ctype)
|
||||||
path to its virtual baseclass. */
|
path to its virtual baseclass. */
|
||||||
if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
|
if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
|
||||||
{
|
{
|
||||||
cp_error_at ("method `%D' may not be declared static",
|
cp_error_at ("`static %#D' cannot be declared", decl);
|
||||||
decl);
|
cp_error_at (" since `virtual %#D' declared in base class",
|
||||||
cp_error_at ("(since `%D' declared virtual in base class.)",
|
|
||||||
tmp);
|
tmp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2288,6 +2288,7 @@ extern tree delta2_identifier;
|
||||||
extern tree pfn_or_delta2_identifier;
|
extern tree pfn_or_delta2_identifier;
|
||||||
extern tree tag_identifier;
|
extern tree tag_identifier;
|
||||||
extern tree vt_off_identifier;
|
extern tree vt_off_identifier;
|
||||||
|
extern tree empty_except_spec;
|
||||||
|
|
||||||
/* A node that is a list (length 1) of error_mark_nodes. */
|
/* A node that is a list (length 1) of error_mark_nodes. */
|
||||||
extern tree error_mark_list;
|
extern tree error_mark_list;
|
||||||
|
@ -3533,7 +3534,7 @@ extern int fntype_p PROTO((tree));
|
||||||
extern tree commonparms PROTO((tree, tree));
|
extern tree commonparms PROTO((tree, tree));
|
||||||
extern tree original_type PROTO((tree));
|
extern tree original_type PROTO((tree));
|
||||||
extern tree common_type PROTO((tree, tree));
|
extern tree common_type PROTO((tree, tree));
|
||||||
extern int compexcepttypes PROTO((tree, tree));
|
extern int comp_except_specs PROTO((tree, tree, int));
|
||||||
extern int comptypes PROTO((tree, tree, int));
|
extern int comptypes PROTO((tree, tree, int));
|
||||||
extern int comp_target_types PROTO((tree, tree, int));
|
extern int comp_target_types PROTO((tree, tree, int));
|
||||||
extern int compparms PROTO((tree, tree));
|
extern int compparms PROTO((tree, tree));
|
||||||
|
@ -3618,6 +3619,7 @@ extern tree build_functional_cast PROTO((tree, tree));
|
||||||
extern char *enum_name_string PROTO((tree, tree));
|
extern char *enum_name_string PROTO((tree, tree));
|
||||||
extern void report_case_error PROTO((int, tree, tree, tree));
|
extern void report_case_error PROTO((int, tree, tree, tree));
|
||||||
extern void check_for_new_type PROTO((const char *, flagged_type_tree));
|
extern void check_for_new_type PROTO((const char *, flagged_type_tree));
|
||||||
|
extern tree add_exception_specifier PROTO((tree, tree, int));
|
||||||
|
|
||||||
/* in xref.c */
|
/* in xref.c */
|
||||||
extern void GNU_xref_begin PROTO((const char *));
|
extern void GNU_xref_begin PROTO((const char *));
|
||||||
|
|
|
@ -336,6 +336,9 @@ tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier;
|
||||||
tree pfn_or_delta2_identifier, tag_identifier;
|
tree pfn_or_delta2_identifier, tag_identifier;
|
||||||
tree vt_off_identifier;
|
tree vt_off_identifier;
|
||||||
|
|
||||||
|
/* Exception specifier used for throw(). */
|
||||||
|
tree empty_except_spec;
|
||||||
|
|
||||||
struct named_label_list
|
struct named_label_list
|
||||||
{
|
{
|
||||||
struct binding_level *binding_level;
|
struct binding_level *binding_level;
|
||||||
|
@ -3478,11 +3481,12 @@ duplicate_decls (newdecl, olddecl)
|
||||||
if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
|
if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
|
||||||
&& DECL_SOURCE_LINE (olddecl) != 0
|
&& DECL_SOURCE_LINE (olddecl) != 0
|
||||||
&& flag_exceptions
|
&& flag_exceptions
|
||||||
&& ! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
|
&& !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
|
||||||
|
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
|
||||||
{
|
{
|
||||||
cp_pedwarn ("declaration of `%D' throws different exceptions",
|
cp_error ("declaration of `%F' throws different exceptions",
|
||||||
newdecl);
|
newdecl);
|
||||||
cp_pedwarn_at ("previous declaration here", olddecl);
|
cp_error_at ("to previous declaration `%F'", olddecl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
|
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
|
||||||
|
@ -6361,6 +6365,7 @@ init_decl_processing ()
|
||||||
const_string_type_node
|
const_string_type_node
|
||||||
= build_pointer_type (build_qualified_type (char_type_node,
|
= build_pointer_type (build_qualified_type (char_type_node,
|
||||||
TYPE_QUAL_CONST));
|
TYPE_QUAL_CONST));
|
||||||
|
empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
|
||||||
#if 0
|
#if 0
|
||||||
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
|
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
|
||||||
#endif
|
#endif
|
||||||
|
@ -6400,8 +6405,7 @@ init_decl_processing ()
|
||||||
c_common_nodes_and_builtins (1, flag_no_builtin, flag_no_nonansi_builtin);
|
c_common_nodes_and_builtins (1, flag_no_builtin, flag_no_nonansi_builtin);
|
||||||
|
|
||||||
void_ftype_ptr
|
void_ftype_ptr
|
||||||
= build_exception_variant (void_ftype_ptr,
|
= build_exception_variant (void_ftype_ptr, empty_except_spec);
|
||||||
tree_cons (NULL_TREE, NULL_TREE, NULL_TREE));
|
|
||||||
|
|
||||||
/* C++ extensions */
|
/* C++ extensions */
|
||||||
|
|
||||||
|
@ -6547,9 +6551,8 @@ init_decl_processing ()
|
||||||
if (flag_honor_std)
|
if (flag_honor_std)
|
||||||
pop_namespace ();
|
pop_namespace ();
|
||||||
newtype = build_exception_variant
|
newtype = build_exception_variant
|
||||||
(ptr_ftype_sizetype, build_tree_list (NULL_TREE, bad_alloc_type_node));
|
(ptr_ftype_sizetype, add_exception_specifier (NULL_TREE, bad_alloc_type_node, -1));
|
||||||
deltype = build_exception_variant
|
deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
|
||||||
(void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE));
|
|
||||||
auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
|
auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
|
||||||
auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
|
auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
|
||||||
global_delete_fndecl
|
global_delete_fndecl
|
||||||
|
|
|
@ -3685,21 +3685,22 @@ exception_specification_opt:
|
||||||
| THROW '(' ansi_raise_identifiers ')' %prec EMPTY
|
| THROW '(' ansi_raise_identifiers ')' %prec EMPTY
|
||||||
{ $$ = $3; }
|
{ $$ = $3; }
|
||||||
| THROW LEFT_RIGHT %prec EMPTY
|
| THROW LEFT_RIGHT %prec EMPTY
|
||||||
{ $$ = build_decl_list (NULL_TREE, NULL_TREE); }
|
{ $$ = empty_except_spec; }
|
||||||
;
|
;
|
||||||
|
|
||||||
ansi_raise_identifier:
|
ansi_raise_identifier:
|
||||||
type_id
|
type_id
|
||||||
{ $$ = build_decl_list (NULL_TREE, groktypename($1.t)); }
|
{
|
||||||
|
check_for_new_type ("exception specifier", $1);
|
||||||
|
$$ = groktypename ($1.t);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
ansi_raise_identifiers:
|
ansi_raise_identifiers:
|
||||||
ansi_raise_identifier
|
ansi_raise_identifier
|
||||||
|
{ $$ = add_exception_specifier (NULL_TREE, $1, 1); }
|
||||||
| ansi_raise_identifiers ',' ansi_raise_identifier
|
| ansi_raise_identifiers ',' ansi_raise_identifier
|
||||||
{
|
{ $$ = add_exception_specifier ($1, $3, 1); }
|
||||||
TREE_CHAIN ($3) = $$;
|
|
||||||
$$ = $3;
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
conversion_declarator:
|
conversion_declarator:
|
||||||
|
|
20
gcc/cp/pt.c
20
gcc/cp/pt.c
|
@ -3937,6 +3937,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
|
||||||
type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
|
type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
|
||||||
SET_DECL_ARTIFICIAL (type_decl);
|
SET_DECL_ARTIFICIAL (type_decl);
|
||||||
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
|
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
|
||||||
|
|
||||||
DECL_SOURCE_FILE (type_decl)
|
DECL_SOURCE_FILE (type_decl)
|
||||||
= DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
|
= DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
|
||||||
DECL_SOURCE_LINE (type_decl)
|
DECL_SOURCE_LINE (type_decl)
|
||||||
|
@ -6499,10 +6500,21 @@ tsubst (t, args, complain, in_decl)
|
||||||
raises = TYPE_RAISES_EXCEPTIONS (t);
|
raises = TYPE_RAISES_EXCEPTIONS (t);
|
||||||
if (raises)
|
if (raises)
|
||||||
{
|
{
|
||||||
raises = tsubst (raises, args, complain, in_decl);
|
tree list = NULL_TREE;
|
||||||
if (raises == error_mark_node)
|
|
||||||
return raises;
|
if (! TREE_VALUE (raises))
|
||||||
fntype = build_exception_variant (fntype, raises);
|
list = raises;
|
||||||
|
else
|
||||||
|
for (; raises != NULL_TREE; raises = TREE_CHAIN (raises))
|
||||||
|
{
|
||||||
|
tree spec = TREE_VALUE (raises);
|
||||||
|
|
||||||
|
spec = tsubst (spec, args, complain, in_decl);
|
||||||
|
if (spec == error_mark_node)
|
||||||
|
return spec;
|
||||||
|
list = add_exception_specifier (list, spec, complain);
|
||||||
|
}
|
||||||
|
fntype = build_exception_variant (fntype, list);
|
||||||
}
|
}
|
||||||
return fntype;
|
return fntype;
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,7 @@ static tree get_virtuals_named_this PROTO((tree, tree));
|
||||||
static tree get_virtual_destructor PROTO((tree, void *));
|
static tree get_virtual_destructor PROTO((tree, void *));
|
||||||
static tree tree_has_any_destructor_p PROTO((tree, void *));
|
static tree tree_has_any_destructor_p PROTO((tree, void *));
|
||||||
static int covariant_return_p PROTO((tree, tree));
|
static int covariant_return_p PROTO((tree, tree));
|
||||||
|
static int check_final_overrider PROTO((tree, tree));
|
||||||
static struct search_level *push_search_level
|
static struct search_level *push_search_level
|
||||||
PROTO((struct stack_level *, struct obstack *));
|
PROTO((struct stack_level *, struct obstack *));
|
||||||
static struct search_level *pop_search_level
|
static struct search_level *pop_search_level
|
||||||
|
@ -1884,6 +1885,63 @@ covariant_return_p (brettype, drettype)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check that virtual overrider OVERRIDER is acceptable for base function
|
||||||
|
BASEFN. Issue diagnostic, and return zero, if unacceptable. */
|
||||||
|
|
||||||
|
int
|
||||||
|
check_final_overrider (overrider, basefn)
|
||||||
|
tree overrider, basefn;
|
||||||
|
{
|
||||||
|
tree over_type = TREE_TYPE (overrider);
|
||||||
|
tree base_type = TREE_TYPE (basefn);
|
||||||
|
tree over_return = TREE_TYPE (over_type);
|
||||||
|
tree base_return = TREE_TYPE (base_type);
|
||||||
|
tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
|
||||||
|
tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (same_type_p (base_return, over_return))
|
||||||
|
/* OK */;
|
||||||
|
else if ((i = covariant_return_p (base_return, over_return)))
|
||||||
|
{
|
||||||
|
if (i == 2)
|
||||||
|
sorry ("adjusting pointers for covariant returns");
|
||||||
|
|
||||||
|
if (pedantic && i == -1)
|
||||||
|
{
|
||||||
|
cp_pedwarn_at ("invalid covariant return type for `virtual %#D'", overrider);
|
||||||
|
cp_pedwarn_at (" overriding `virtual %#D' (must be pointer or reference to class)", basefn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IS_AGGR_TYPE_2 (base_return, over_return)
|
||||||
|
&& same_or_base_type_p (base_return, over_return))
|
||||||
|
{
|
||||||
|
cp_error_at ("invalid covariant return type for `virtual %#D'", overrider);
|
||||||
|
cp_error_at (" overriding `virtual %#D' (must use pointer or reference)", basefn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)) == NULL_TREE)
|
||||||
|
{
|
||||||
|
cp_error_at ("conflicting return type specified for `virtual %#D'", overrider);
|
||||||
|
cp_error_at (" overriding `virtual %#D'", basefn);
|
||||||
|
SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
|
||||||
|
DECL_CLASS_CONTEXT (overrider));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check throw specifier is subset. */
|
||||||
|
/* XXX At the moment, punt on an overriding artificial function. We
|
||||||
|
don't generate its exception specifier, so can't check it properly. */
|
||||||
|
if (! DECL_ARTIFICIAL (overrider)
|
||||||
|
&& !comp_except_specs (base_throw, over_throw, 0))
|
||||||
|
{
|
||||||
|
cp_error_at ("looser throw specifier for `virtual %#F'", overrider);
|
||||||
|
cp_error_at (" overriding `virtual %#F'", basefn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Given a class type TYPE, and a function decl FNDECL, look for a
|
/* Given a class type TYPE, and a function decl FNDECL, look for a
|
||||||
virtual function in TYPE's hierarchy which FNDECL could match as a
|
virtual function in TYPE's hierarchy which FNDECL could match as a
|
||||||
virtual function. It doesn't matter which one we find.
|
virtual function. It doesn't matter which one we find.
|
||||||
|
@ -1897,7 +1955,6 @@ get_matching_virtual (binfo, fndecl, dtorp)
|
||||||
int dtorp;
|
int dtorp;
|
||||||
{
|
{
|
||||||
tree tmp = NULL_TREE;
|
tree tmp = NULL_TREE;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (TREE_CODE (fndecl) == TEMPLATE_DECL)
|
if (TREE_CODE (fndecl) == TEMPLATE_DECL)
|
||||||
/* In [temp.mem] we have:
|
/* In [temp.mem] we have:
|
||||||
|
@ -1914,9 +1971,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tree drettype, dtypes, btypes, instptr_type;
|
tree drettype, dtypes, btypes, instptr_type;
|
||||||
tree basetype = DECL_CLASS_CONTEXT (fndecl);
|
|
||||||
tree baselink, best = NULL_TREE;
|
tree baselink, best = NULL_TREE;
|
||||||
tree name = DECL_ASSEMBLER_NAME (fndecl);
|
|
||||||
tree declarator = DECL_NAME (fndecl);
|
tree declarator = DECL_NAME (fndecl);
|
||||||
if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
|
if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
@ -1958,33 +2013,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
|
||||||
== TYPE_QUALS (instptr_type))
|
== TYPE_QUALS (instptr_type))
|
||||||
&& compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
|
&& compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
|
||||||
{
|
{
|
||||||
tree brettype = TREE_TYPE (TREE_TYPE (tmp));
|
check_final_overrider (fndecl, tmp);
|
||||||
if (same_type_p (brettype, drettype))
|
|
||||||
/* OK */;
|
|
||||||
else if ((i = covariant_return_p (brettype, drettype)))
|
|
||||||
{
|
|
||||||
if (i == 2)
|
|
||||||
sorry ("adjusting pointers for covariant returns");
|
|
||||||
|
|
||||||
if (pedantic && i == -1)
|
|
||||||
{
|
|
||||||
cp_pedwarn_at ("invalid covariant return type for `%#D' (must be pointer or reference to class)", fndecl);
|
|
||||||
cp_pedwarn_at (" overriding `%#D'", tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (IS_AGGR_TYPE_2 (brettype, drettype)
|
|
||||||
&& same_or_base_type_p (brettype, drettype))
|
|
||||||
{
|
|
||||||
error ("invalid covariant return type (must use pointer or reference)");
|
|
||||||
cp_error_at (" overriding `%#D'", tmp);
|
|
||||||
cp_error_at (" with `%#D'", fndecl);
|
|
||||||
}
|
|
||||||
else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE)
|
|
||||||
{
|
|
||||||
cp_error_at ("conflicting return type specified for virtual function `%#D'", fndecl);
|
|
||||||
cp_error_at (" overriding definition as `%#D'", tmp);
|
|
||||||
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FNDECL overrides this function. We continue to
|
/* FNDECL overrides this function. We continue to
|
||||||
check all the other functions in order to catch
|
check all the other functions in order to catch
|
||||||
|
|
|
@ -1484,25 +1484,9 @@ build_exception_variant (type, raises)
|
||||||
int type_quals = TYPE_QUALS (type);
|
int type_quals = TYPE_QUALS (type);
|
||||||
|
|
||||||
for (; v; v = TYPE_NEXT_VARIANT (v))
|
for (; v; v = TYPE_NEXT_VARIANT (v))
|
||||||
{
|
if (TYPE_QUALS (v) == type_quals
|
||||||
tree t;
|
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
|
||||||
tree u;
|
return v;
|
||||||
|
|
||||||
if (TYPE_QUALS (v) != type_quals)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises;
|
|
||||||
t != NULL_TREE && u != NULL_TREE;
|
|
||||||
t = TREE_CHAIN (t), u = TREE_CHAIN (u))
|
|
||||||
if (((TREE_VALUE (t) != NULL_TREE)
|
|
||||||
!= (TREE_VALUE (u) != NULL_TREE))
|
|
||||||
|| !same_type_p (TREE_VALUE (t), TREE_VALUE (u)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!t && !u)
|
|
||||||
/* There's a memory leak here; RAISES is not freed. */
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Need to build a new variant. */
|
/* Need to build a new variant. */
|
||||||
v = build_type_copy (type);
|
v = build_type_copy (type);
|
||||||
|
|
105
gcc/cp/typeck.c
105
gcc/cp/typeck.c
|
@ -48,6 +48,7 @@ static int comp_target_parms PROTO((tree, tree, int));
|
||||||
static int comp_ptr_ttypes_real PROTO((tree, tree, int));
|
static int comp_ptr_ttypes_real PROTO((tree, tree, int));
|
||||||
static int comp_ptr_ttypes_const PROTO((tree, tree));
|
static int comp_ptr_ttypes_const PROTO((tree, tree));
|
||||||
static int comp_ptr_ttypes_reinterpret PROTO((tree, tree));
|
static int comp_ptr_ttypes_reinterpret PROTO((tree, tree));
|
||||||
|
static int comp_except_types PROTO((tree, tree, int));
|
||||||
static int comp_array_types PROTO((int (*) (tree, tree, int), tree,
|
static int comp_array_types PROTO((int (*) (tree, tree, int), tree,
|
||||||
tree, int));
|
tree, int));
|
||||||
static tree common_base_type PROTO((tree, tree));
|
static tree common_base_type PROTO((tree, tree));
|
||||||
|
@ -853,13 +854,102 @@ common_type (t1, t2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if TYPE1 and TYPE2 raise the same exceptions. */
|
/* Compare two exception specifier types for exactness or subsetness, if
|
||||||
|
allowed. Returns 0 for mismatch, 1 for same, 2 if B is allowed by A.
|
||||||
|
|
||||||
|
[except.spec] "If a class X ... objects of class X or any class publicly
|
||||||
|
and unambigously derrived from X. Similarly, if a pointer type Y * ...
|
||||||
|
exceptions of type Y * or that are pointers to any type publicly and
|
||||||
|
unambigously derrived from Y. Otherwise a function only allows exceptions
|
||||||
|
that have the same type ..."
|
||||||
|
This does not mention cv qualifiers and is different to what throw
|
||||||
|
[except.throw] and catch [except.catch] will do. They will ignore the
|
||||||
|
top level cv qualifiers, and allow qualifiers in the pointer to class
|
||||||
|
example.
|
||||||
|
|
||||||
|
We implement the letter of the standard. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
comp_except_types (a, b, exact)
|
||||||
|
tree a, b;
|
||||||
|
int exact;
|
||||||
|
{
|
||||||
|
if (same_type_p (a, b))
|
||||||
|
return 1;
|
||||||
|
else if (!exact)
|
||||||
|
{
|
||||||
|
if (CP_TYPE_QUALS (a) || CP_TYPE_QUALS (b))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (TREE_CODE (a) == POINTER_TYPE
|
||||||
|
&& TREE_CODE (b) == POINTER_TYPE)
|
||||||
|
{
|
||||||
|
a = TREE_TYPE (a);
|
||||||
|
b = TREE_TYPE (b);
|
||||||
|
if (CP_TYPE_QUALS (a) || CP_TYPE_QUALS (b))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TREE_CODE (a) != RECORD_TYPE
|
||||||
|
|| TREE_CODE (b) != RECORD_TYPE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (ACCESSIBLY_UNIQUELY_DERIVED_P (a, b))
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return 1 if TYPE1 and TYPE2 are equivalent exception specifiers.
|
||||||
|
If EXACT is 0, T2 can be a subset of T1 (according to 15.4/7),
|
||||||
|
otherwise it must be exact. Exception lists are unordered, but
|
||||||
|
we've already filtered out duplicates. Most lists will be in order,
|
||||||
|
we should try to make use of that. */
|
||||||
|
|
||||||
int
|
int
|
||||||
compexcepttypes (t1, t2)
|
comp_except_specs (t1, t2, exact)
|
||||||
tree t1, t2;
|
tree t1, t2;
|
||||||
|
int exact;
|
||||||
{
|
{
|
||||||
return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);
|
tree probe;
|
||||||
|
tree base;
|
||||||
|
int length = 0;
|
||||||
|
|
||||||
|
if (t1 == t2)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (t1 == NULL_TREE) /* T1 is ... */
|
||||||
|
return t2 == NULL_TREE || !exact;
|
||||||
|
if (!TREE_VALUE (t1)) /* t1 is EMPTY */
|
||||||
|
return t2 != NULL_TREE && !TREE_VALUE (t2);
|
||||||
|
if (t2 == NULL_TREE) /* T2 is ... */
|
||||||
|
return 0;
|
||||||
|
if (TREE_VALUE(t1) && !TREE_VALUE (t2)) /* T2 is EMPTY, T1 is not */
|
||||||
|
return !exact;
|
||||||
|
|
||||||
|
/* Neither set is ... or EMPTY, make sure each part of T2 is in T1.
|
||||||
|
Count how many we find, to determine exactness. For exact matching and
|
||||||
|
ordered T1, T2, this is an O(n) operation, otherwise its worst case is
|
||||||
|
O(nm). */
|
||||||
|
for (base = t1; t2 != NULL_TREE; t2 = TREE_CHAIN (t2))
|
||||||
|
{
|
||||||
|
for (probe = base; probe != NULL_TREE; probe = TREE_CHAIN (probe))
|
||||||
|
{
|
||||||
|
tree a = TREE_VALUE (probe);
|
||||||
|
tree b = TREE_VALUE (t2);
|
||||||
|
|
||||||
|
if (comp_except_types (a, b, exact))
|
||||||
|
{
|
||||||
|
if (probe == base && exact)
|
||||||
|
base = TREE_CHAIN (probe);
|
||||||
|
length++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (probe == NULL_TREE)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return !exact || base == NULL_TREE || length == list_length (t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare the array types T1 and T2, using CMP as the type comparison
|
/* Compare the array types T1 and T2, using CMP as the type comparison
|
||||||
|
@ -1031,7 +1121,8 @@ comptypes (t1, t2, strict)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case METHOD_TYPE:
|
case METHOD_TYPE:
|
||||||
if (! compexcepttypes (t1, t2))
|
if (! comp_except_specs (TYPE_RAISES_EXCEPTIONS (t1),
|
||||||
|
TYPE_RAISES_EXCEPTIONS (t2), 1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* This case is anti-symmetrical!
|
/* This case is anti-symmetrical!
|
||||||
|
@ -1058,7 +1149,8 @@ comptypes (t1, t2, strict)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FUNCTION_TYPE:
|
case FUNCTION_TYPE:
|
||||||
if (! compexcepttypes (t1, t2))
|
if (! comp_except_specs (TYPE_RAISES_EXCEPTIONS (t1),
|
||||||
|
TYPE_RAISES_EXCEPTIONS (t2), 1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
val = ((TREE_TYPE (t1) == TREE_TYPE (t2)
|
val = ((TREE_TYPE (t1) == TREE_TYPE (t2)
|
||||||
|
@ -2175,6 +2267,9 @@ build_component_ref (datum, component, basetype_path, protect)
|
||||||
tree name = component;
|
tree name = component;
|
||||||
if (TREE_CODE (component) == VAR_DECL)
|
if (TREE_CODE (component) == VAR_DECL)
|
||||||
name = DECL_NAME (component);
|
name = DECL_NAME (component);
|
||||||
|
if (TREE_CODE (component) == NAMESPACE_DECL)
|
||||||
|
/* Source is in error, but produce a sensible diagnostic. */
|
||||||
|
name = DECL_NAME (component);
|
||||||
if (basetype_path == NULL_TREE)
|
if (basetype_path == NULL_TREE)
|
||||||
basetype_path = TYPE_BINFO (basetype);
|
basetype_path = TYPE_BINFO (basetype);
|
||||||
field = lookup_field (basetype_path, name,
|
field = lookup_field (basetype_path, name,
|
||||||
|
|
|
@ -1520,3 +1520,56 @@ check_for_new_type (string, inptree)
|
||||||
&& (pedantic || strcmp (string, "cast") != 0))
|
&& (pedantic || strcmp (string, "cast") != 0))
|
||||||
pedwarn ("ANSI C++ forbids defining types within %s",string);
|
pedwarn ("ANSI C++ forbids defining types within %s",string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add new exception specifier SPEC, to the LIST we currently have.
|
||||||
|
If it's already in LIST then do nothing.
|
||||||
|
Moan if it's bad and we're allowed to. COMPLAIN < 0 means we
|
||||||
|
know what we're doing. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
add_exception_specifier (list, spec, complain)
|
||||||
|
tree list, spec;
|
||||||
|
int complain;
|
||||||
|
{
|
||||||
|
int ok;
|
||||||
|
tree core = spec;
|
||||||
|
int is_ptr;
|
||||||
|
|
||||||
|
if (spec == error_mark_node)
|
||||||
|
return list;
|
||||||
|
|
||||||
|
my_friendly_assert (spec && (!list || TREE_VALUE (list)), 19990317);
|
||||||
|
|
||||||
|
/* [except.spec] 1, type in an exception specifier shall not be
|
||||||
|
incomplete, or pointer or ref to incomplete other than pointer
|
||||||
|
to cv void. */
|
||||||
|
is_ptr = TREE_CODE (core) == POINTER_TYPE;
|
||||||
|
if (is_ptr || TREE_CODE (core) == REFERENCE_TYPE)
|
||||||
|
core = TREE_TYPE (core);
|
||||||
|
if (complain < 0)
|
||||||
|
ok = 1;
|
||||||
|
else if (TYPE_MAIN_VARIANT (core) == void_type_node)
|
||||||
|
ok = is_ptr;
|
||||||
|
else if (TREE_CODE (core) == TEMPLATE_TYPE_PARM)
|
||||||
|
ok = 1;
|
||||||
|
else
|
||||||
|
ok = TYPE_SIZE (core) != NULL_TREE;
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
tree probe;
|
||||||
|
|
||||||
|
for (probe = list; probe; probe = TREE_CHAIN (probe))
|
||||||
|
if (same_type_p (TREE_VALUE (probe), spec))
|
||||||
|
break;
|
||||||
|
if (!probe)
|
||||||
|
{
|
||||||
|
spec = build_decl_list (NULL_TREE, spec);
|
||||||
|
TREE_CHAIN (spec) = list;
|
||||||
|
list = spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (complain)
|
||||||
|
incomplete_type_error (NULL_TREE, core);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue