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>
|
||||
|
||||
* call.c (convert_arg_to_ellipsis): Use pod_type_p.
|
||||
|
|
|
@ -2977,9 +2977,8 @@ check_for_override (decl, ctype)
|
|||
path to its virtual baseclass. */
|
||||
if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
|
||||
{
|
||||
cp_error_at ("method `%D' may not be declared static",
|
||||
decl);
|
||||
cp_error_at ("(since `%D' declared virtual in base class.)",
|
||||
cp_error_at ("`static %#D' cannot be declared", decl);
|
||||
cp_error_at (" since `virtual %#D' declared in base class",
|
||||
tmp);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2288,6 +2288,7 @@ extern tree delta2_identifier;
|
|||
extern tree pfn_or_delta2_identifier;
|
||||
extern tree tag_identifier;
|
||||
extern tree vt_off_identifier;
|
||||
extern tree empty_except_spec;
|
||||
|
||||
/* A node that is a list (length 1) of error_mark_nodes. */
|
||||
extern tree error_mark_list;
|
||||
|
@ -3533,7 +3534,7 @@ extern int fntype_p PROTO((tree));
|
|||
extern tree commonparms PROTO((tree, tree));
|
||||
extern tree original_type PROTO((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 comp_target_types PROTO((tree, tree, int));
|
||||
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 void report_case_error PROTO((int, tree, tree, 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 */
|
||||
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 vt_off_identifier;
|
||||
|
||||
/* Exception specifier used for throw(). */
|
||||
tree empty_except_spec;
|
||||
|
||||
struct named_label_list
|
||||
{
|
||||
struct binding_level *binding_level;
|
||||
|
@ -3478,11 +3481,12 @@ duplicate_decls (newdecl, olddecl)
|
|||
if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
|
||||
&& DECL_SOURCE_LINE (olddecl) != 0
|
||||
&& 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);
|
||||
cp_pedwarn_at ("previous declaration here", olddecl);
|
||||
cp_error_at ("to previous declaration `%F'", olddecl);
|
||||
}
|
||||
}
|
||||
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
|
||||
|
@ -6361,6 +6365,7 @@ init_decl_processing ()
|
|||
const_string_type_node
|
||||
= build_pointer_type (build_qualified_type (char_type_node,
|
||||
TYPE_QUAL_CONST));
|
||||
empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
|
||||
#if 0
|
||||
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
|
||||
#endif
|
||||
|
@ -6400,8 +6405,7 @@ init_decl_processing ()
|
|||
c_common_nodes_and_builtins (1, flag_no_builtin, flag_no_nonansi_builtin);
|
||||
|
||||
void_ftype_ptr
|
||||
= build_exception_variant (void_ftype_ptr,
|
||||
tree_cons (NULL_TREE, NULL_TREE, NULL_TREE));
|
||||
= build_exception_variant (void_ftype_ptr, empty_except_spec);
|
||||
|
||||
/* C++ extensions */
|
||||
|
||||
|
@ -6547,9 +6551,8 @@ init_decl_processing ()
|
|||
if (flag_honor_std)
|
||||
pop_namespace ();
|
||||
newtype = build_exception_variant
|
||||
(ptr_ftype_sizetype, build_tree_list (NULL_TREE, bad_alloc_type_node));
|
||||
deltype = build_exception_variant
|
||||
(void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE));
|
||||
(ptr_ftype_sizetype, add_exception_specifier (NULL_TREE, bad_alloc_type_node, -1));
|
||||
deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
|
||||
auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
|
||||
auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
|
||||
global_delete_fndecl
|
||||
|
|
|
@ -3685,21 +3685,22 @@ exception_specification_opt:
|
|||
| THROW '(' ansi_raise_identifiers ')' %prec EMPTY
|
||||
{ $$ = $3; }
|
||||
| THROW LEFT_RIGHT %prec EMPTY
|
||||
{ $$ = build_decl_list (NULL_TREE, NULL_TREE); }
|
||||
{ $$ = empty_except_spec; }
|
||||
;
|
||||
|
||||
ansi_raise_identifier:
|
||||
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_identifier
|
||||
{ $$ = add_exception_specifier (NULL_TREE, $1, 1); }
|
||||
| ansi_raise_identifiers ',' ansi_raise_identifier
|
||||
{
|
||||
TREE_CHAIN ($3) = $$;
|
||||
$$ = $3;
|
||||
}
|
||||
{ $$ = add_exception_specifier ($1, $3, 1); }
|
||||
;
|
||||
|
||||
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);
|
||||
SET_DECL_ARTIFICIAL (type_decl);
|
||||
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
|
||||
|
||||
DECL_SOURCE_FILE (type_decl)
|
||||
= DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
|
||||
DECL_SOURCE_LINE (type_decl)
|
||||
|
@ -6499,10 +6500,21 @@ tsubst (t, args, complain, in_decl)
|
|||
raises = TYPE_RAISES_EXCEPTIONS (t);
|
||||
if (raises)
|
||||
{
|
||||
raises = tsubst (raises, args, complain, in_decl);
|
||||
if (raises == error_mark_node)
|
||||
return raises;
|
||||
fntype = build_exception_variant (fntype, raises);
|
||||
tree list = NULL_TREE;
|
||||
|
||||
if (! TREE_VALUE (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;
|
||||
}
|
||||
|
|
|
@ -117,6 +117,7 @@ static tree get_virtuals_named_this PROTO((tree, tree));
|
|||
static tree get_virtual_destructor PROTO((tree, void *));
|
||||
static tree tree_has_any_destructor_p PROTO((tree, void *));
|
||||
static int covariant_return_p PROTO((tree, tree));
|
||||
static int check_final_overrider PROTO((tree, tree));
|
||||
static struct search_level *push_search_level
|
||||
PROTO((struct stack_level *, struct obstack *));
|
||||
static struct search_level *pop_search_level
|
||||
|
@ -1884,6 +1885,63 @@ covariant_return_p (brettype, drettype)
|
|||
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
|
||||
virtual function in TYPE's hierarchy which FNDECL could match as a
|
||||
virtual function. It doesn't matter which one we find.
|
||||
|
@ -1897,7 +1955,6 @@ get_matching_virtual (binfo, fndecl, dtorp)
|
|||
int dtorp;
|
||||
{
|
||||
tree tmp = NULL_TREE;
|
||||
int i;
|
||||
|
||||
if (TREE_CODE (fndecl) == TEMPLATE_DECL)
|
||||
/* In [temp.mem] we have:
|
||||
|
@ -1914,9 +1971,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
|
|||
else
|
||||
{
|
||||
tree drettype, dtypes, btypes, instptr_type;
|
||||
tree basetype = DECL_CLASS_CONTEXT (fndecl);
|
||||
tree baselink, best = NULL_TREE;
|
||||
tree name = DECL_ASSEMBLER_NAME (fndecl);
|
||||
tree declarator = DECL_NAME (fndecl);
|
||||
if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
|
||||
return NULL_TREE;
|
||||
|
@ -1958,33 +2013,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
|
|||
== TYPE_QUALS (instptr_type))
|
||||
&& compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
|
||||
{
|
||||
tree brettype = TREE_TYPE (TREE_TYPE (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);
|
||||
}
|
||||
check_final_overrider (fndecl, tmp);
|
||||
|
||||
/* FNDECL overrides this function. We continue to
|
||||
check all the other functions in order to catch
|
||||
|
|
|
@ -1484,25 +1484,9 @@ build_exception_variant (type, raises)
|
|||
int type_quals = TYPE_QUALS (type);
|
||||
|
||||
for (; v; v = TYPE_NEXT_VARIANT (v))
|
||||
{
|
||||
tree t;
|
||||
tree u;
|
||||
|
||||
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. */
|
||||
if (TYPE_QUALS (v) == type_quals
|
||||
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Need to build a new variant. */
|
||||
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_const 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,
|
||||
tree, int));
|
||||
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
|
||||
compexcepttypes (t1, t2)
|
||||
comp_except_specs (t1, t2, exact)
|
||||
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
|
||||
|
@ -1031,7 +1121,8 @@ comptypes (t1, t2, strict)
|
|||
break;
|
||||
|
||||
case METHOD_TYPE:
|
||||
if (! compexcepttypes (t1, t2))
|
||||
if (! comp_except_specs (TYPE_RAISES_EXCEPTIONS (t1),
|
||||
TYPE_RAISES_EXCEPTIONS (t2), 1))
|
||||
return 0;
|
||||
|
||||
/* This case is anti-symmetrical!
|
||||
|
@ -1058,7 +1149,8 @@ comptypes (t1, t2, strict)
|
|||
break;
|
||||
|
||||
case FUNCTION_TYPE:
|
||||
if (! compexcepttypes (t1, t2))
|
||||
if (! comp_except_specs (TYPE_RAISES_EXCEPTIONS (t1),
|
||||
TYPE_RAISES_EXCEPTIONS (t2), 1))
|
||||
return 0;
|
||||
|
||||
val = ((TREE_TYPE (t1) == TREE_TYPE (t2)
|
||||
|
@ -2175,6 +2267,9 @@ build_component_ref (datum, component, basetype_path, protect)
|
|||
tree name = component;
|
||||
if (TREE_CODE (component) == VAR_DECL)
|
||||
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)
|
||||
basetype_path = TYPE_BINFO (basetype);
|
||||
field = lookup_field (basetype_path, name,
|
||||
|
|
|
@ -1520,3 +1520,56 @@ check_for_new_type (string, inptree)
|
|||
&& (pedantic || strcmp (string, "cast") != 0))
|
||||
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