Commit 9f4faeae by Mark Mitchell Committed by Mark Mitchell

re PR c++/19733 (ICE on invalid destructor call)

	PR c++/19733
	* class.c (add_method): Don't set TYPE_HAS_DESTRUCTOR.
	(check_bases): Give warnings about a base class with a
	non-virtual destructor, even if it is implicit.
	(finish_struct_bits): Don't copy TYPE_HAS_DESTRUCTOR.
	(maybe_warn_about_overly_private_class): Don't use
	TYPE_HAS_DESTRUCTOR.
	(finish_struct_methods): Don't set TYPE_HAS_DESTRUCTOR.
	(check_for_override): Give it external linkage.
	(add_implicitly_declared_members): Generate destructors lazily.
	(check_field_decls): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR, not
	TYPE_HAS_DESTRUCTOR.
	(check_bases_and_members): Call check_methods before
	check_field_decls.
	(check_bases_and_members): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR, not
	TYPE_HAS_DESTRUCTOR.
	(finish_struct_1): Do not use TYPE_HAS_DESTRUCTOR.
	* cp-tree.def (PSEUDO_DTOR_EXPR): Document.
	* cp-tree.h (TYPE_HAS_DESTRUCTOR): Remove.
	(lang_type_class): Add lazy_destructor.
	(CLASSTYPE_LAZY_DESTRUCTOR): New macro.
	(CLASSTYPE_DESTRUCTORS): Robustify.
	(TYPE_HAS_DESTRUCTOR): Remove.
	(check_for_override): Declare.
	(build_vbase_delete): Remove.
	* cvt.c (convert_to_void): Issue errors about pseudo-destructor
	expressions.
	* decl.c (cxx_maybe_build_cleanup): Remove dead code.
	* except.c (dtor_nothrow): Lazily create destructors if necessary.
	(build_throw): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
	* init.c (build_delete): Lazily create destructors, if necessary.
	(build_vbase_delete): Remove.
	* method.c (locate_dtor): Simplify.
	(implicitly_declare_fn): Add support for destructors.
	* parser.c (cp_parser_lookup_name): Lazily create destructors, if
	necessary.
	* pt.c (check_explicit_specialization): Don't use
	TYPE_HAS_DESTRUCTOR.
	(instantiate_class_template): Likewise.
	* ptree.c (cxx_print_type): Don't print TYPE_HAS_DESTRUCTOR.
	* rtti.c (emit_support_tinfos): Robustify.
	* search.c (lookup_fnfields_1): Lazily create destructors.
	* typeck.c (build_class_member_access_expr): Remove
	PSEUDO_DTOR_EXPR handling.
	(lookup_destructor): Likewise.

	PR c++/19733
	* g++.dg/parse/crash23.C: New test.
	* g++.dg/warn/Weff1.C: New test.

From-SVN: r94759
parent ec2cd8b2
2005-02-08 Mark Mitchell <mark@codesourcery.com>
PR c++/19733
* class.c (add_method): Don't set TYPE_HAS_DESTRUCTOR.
(check_bases): Give warnings about a base class with a
non-virtual destructor, even if it is implicit.
(finish_struct_bits): Don't copy TYPE_HAS_DESTRUCTOR.
(maybe_warn_about_overly_private_class): Don't use
TYPE_HAS_DESTRUCTOR.
(finish_struct_methods): Don't set TYPE_HAS_DESTRUCTOR.
(check_for_override): Give it external linkage.
(add_implicitly_declared_members): Generate destructors lazily.
(check_field_decls): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR, not
TYPE_HAS_DESTRUCTOR.
(check_bases_and_members): Call check_methods before
check_field_decls.
(check_bases_and_members): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR, not
TYPE_HAS_DESTRUCTOR.
(finish_struct_1): Do not use TYPE_HAS_DESTRUCTOR.
* cp-tree.def (PSEUDO_DTOR_EXPR): Document.
* cp-tree.h (TYPE_HAS_DESTRUCTOR): Remove.
(lang_type_class): Add lazy_destructor.
(CLASSTYPE_LAZY_DESTRUCTOR): New macro.
(CLASSTYPE_DESTRUCTORS): Robustify.
(TYPE_HAS_DESTRUCTOR): Remove.
(check_for_override): Declare.
(build_vbase_delete): Remove.
* cvt.c (convert_to_void): Issue errors about pseudo-destructor
expressions.
* decl.c (cxx_maybe_build_cleanup): Remove dead code.
* except.c (dtor_nothrow): Lazily create destructors if necessary.
(build_throw): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
* init.c (build_delete): Lazily create destructors, if necessary.
(build_vbase_delete): Remove.
* method.c (locate_dtor): Simplify.
(implicitly_declare_fn): Add support for destructors.
* parser.c (cp_parser_lookup_name): Lazily create destructors, if
necessary.
* pt.c (check_explicit_specialization): Don't use
TYPE_HAS_DESTRUCTOR.
(instantiate_class_template): Likewise.
* ptree.c (cxx_print_type): Don't print TYPE_HAS_DESTRUCTOR.
* rtti.c (emit_support_tinfos): Robustify.
* search.c (lookup_fnfields_1): Lazily create destructors.
* typeck.c (build_class_member_access_expr): Remove
PSEUDO_DTOR_EXPR handling.
(lookup_destructor): Likewise.
2005-02-08 Kazu Hirata <kazu@cs.umass.edu> 2005-02-08 Kazu Hirata <kazu@cs.umass.edu>
* cxx-pretty-print.c, cxx-pretty-print.h, decl.h: Update * cxx-pretty-print.c, cxx-pretty-print.h, decl.h: Update
......
...@@ -222,6 +222,18 @@ DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", tcc_expression, 2) ...@@ -222,6 +222,18 @@ DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", tcc_expression, 2)
the original name, and the parameter is the FUNCTION_DECL. */ the original name, and the parameter is the FUNCTION_DECL. */
DEFTREECODE (OVERLOAD, "overload", tcc_exceptional, 0) DEFTREECODE (OVERLOAD, "overload", tcc_exceptional, 0)
/* A pseudo-destructor, of the form "OBJECT.~DESTRUCTOR" or
"OBJECT.SCOPE::~DESTRUCTOR. The first operand is the OBJECT. The
second operand (if non-NULL) is the SCOPE. The third operand is
the TYPE node corresponding to the DESTRUCTOR. The type of the
first operand will always be a scalar type.
The type of a PSEUDO_DTOR_EXPR is always "void", even though it can
be used as if it were a zero-argument function. We handle the
function-call case specially, and giving it "void" type prevents it
being used in expressions in ways that are not permitted. */
DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", tcc_expression, 3)
/* A whole bunch of tree codes for the initial, superficial parsing of /* A whole bunch of tree codes for the initial, superficial parsing of
templates. */ templates. */
DEFTREECODE (MODOP_EXPR, "modop_expr", tcc_expression, 3) DEFTREECODE (MODOP_EXPR, "modop_expr", tcc_expression, 3)
...@@ -232,7 +244,6 @@ DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", tcc_unary, 1) ...@@ -232,7 +244,6 @@ DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", tcc_unary, 1)
DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", tcc_unary, 1) DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", tcc_unary, 1)
DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", tcc_expression, 2) DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", tcc_expression, 2)
DEFTREECODE (TYPEID_EXPR, "typeid_expr", tcc_expression, 1) DEFTREECODE (TYPEID_EXPR, "typeid_expr", tcc_expression, 1)
DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", tcc_expression, 3)
/* A placeholder for an expression that is not type-dependent, but /* A placeholder for an expression that is not type-dependent, but
does occur in a template. When an expression that is not does occur in a template. When an expression that is not
......
...@@ -80,7 +80,7 @@ struct diagnostic_context; ...@@ -80,7 +80,7 @@ struct diagnostic_context;
Usage of TYPE_LANG_FLAG_?: Usage of TYPE_LANG_FLAG_?:
0: TYPE_DEPENDENT_P 0: TYPE_DEPENDENT_P
1: TYPE_HAS_CONSTRUCTOR. 1: TYPE_HAS_CONSTRUCTOR.
2: TYPE_HAS_DESTRUCTOR. 2: Unused
3: TYPE_FOR_JAVA. 3: TYPE_FOR_JAVA.
4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR 4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR
5: IS_AGGR_TYPE. 5: IS_AGGR_TYPE.
...@@ -1035,8 +1035,9 @@ struct lang_type_class GTY(()) ...@@ -1035,8 +1035,9 @@ struct lang_type_class GTY(())
unsigned lazy_default_ctor : 1; unsigned lazy_default_ctor : 1;
unsigned lazy_copy_ctor : 1; unsigned lazy_copy_ctor : 1;
unsigned lazy_assignment_op : 1; unsigned lazy_assignment_op : 1;
unsigned lazy_destructor : 1;
unsigned has_const_init_ref : 1; unsigned has_const_init_ref : 1;
unsigned has_complex_init_ref : 1; unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1; unsigned has_complex_assign_ref : 1;
unsigned non_aggregate : 1; unsigned non_aggregate : 1;
...@@ -1049,7 +1050,7 @@ struct lang_type_class GTY(()) ...@@ -1049,7 +1050,7 @@ struct lang_type_class GTY(())
/* There are some bits left to fill out a 32-bit word. Keep track /* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or of this by updating the size of this bitfield whenever you add or
remove a flag. */ remove a flag. */
unsigned dummy : 12; unsigned dummy : 11;
tree primary_base; tree primary_base;
VEC (tree_pair_s) *vcall_indices; VEC (tree_pair_s) *vcall_indices;
...@@ -1153,6 +1154,11 @@ struct lang_type GTY(()) ...@@ -1153,6 +1154,11 @@ struct lang_type GTY(())
#define CLASSTYPE_LAZY_ASSIGNMENT_OP(NODE) \ #define CLASSTYPE_LAZY_ASSIGNMENT_OP(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->lazy_assignment_op) (LANG_TYPE_CLASS_CHECK (NODE)->lazy_assignment_op)
/* Nonzero means that NODE (a class type) has a destructor -- but that
it has not yet been declared. */
#define CLASSTYPE_LAZY_DESTRUCTOR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->lazy_destructor)
/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */ /* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */
#define TYPE_HAS_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_assign_ref) #define TYPE_HAS_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_assign_ref)
...@@ -1236,9 +1242,13 @@ struct lang_type GTY(()) ...@@ -1236,9 +1242,13 @@ struct lang_type GTY(())
(VEC_index (tree, CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT)) (VEC_index (tree, CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT))
/* A FUNCTION_DECL for the destructor for NODE. These are the /* A FUNCTION_DECL for the destructor for NODE. These are the
destructors that take an in-charge parameter. */ destructors that take an in-charge parameter. If
CLASSTYPE_LAZY_DESTRUCTOR is true, then this entry will be NULL
until the destructor is created with lazily_declare_fn. */
#define CLASSTYPE_DESTRUCTORS(NODE) \ #define CLASSTYPE_DESTRUCTORS(NODE) \
(VEC_index (tree, CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT)) (CLASSTYPE_METHOD_VEC (NODE) \
? VEC_index (tree, CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT) \
: NULL_TREE)
/* A dictionary of the nested user-defined-types (class-types, or enums) /* A dictionary of the nested user-defined-types (class-types, or enums)
found within this class. This table includes nested member class found within this class. This table includes nested member class
...@@ -2412,9 +2422,6 @@ struct lang_decl GTY(()) ...@@ -2412,9 +2422,6 @@ struct lang_decl GTY(())
&& CONSTRUCTOR_ELTS (NODE) == NULL_TREE \ && CONSTRUCTOR_ELTS (NODE) == NULL_TREE \
&& ! TREE_HAS_CONSTRUCTOR (NODE)) && ! TREE_HAS_CONSTRUCTOR (NODE))
/* Nonzero for _TYPE means that the _TYPE defines a destructor. */
#define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2 (NODE))
/* Nonzero means that an object of this type can not be initialized using /* Nonzero means that an object of this type can not be initialized using
an initializer list. */ an initializer list. */
#define CLASSTYPE_NON_AGGREGATE(NODE) \ #define CLASSTYPE_NON_AGGREGATE(NODE) \
...@@ -3721,6 +3728,7 @@ extern void debug_thunks (tree); ...@@ -3721,6 +3728,7 @@ extern void debug_thunks (tree);
extern tree cp_fold_obj_type_ref (tree, tree); extern tree cp_fold_obj_type_ref (tree, tree);
extern void set_linkage_according_to_type (tree, tree); extern void set_linkage_according_to_type (tree, tree);
extern void determine_key_method (tree); extern void determine_key_method (tree);
extern void check_for_override (tree, tree);
/* in cvt.c */ /* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree); extern tree convert_to_reference (tree, tree, int, int, tree);
...@@ -3924,7 +3932,6 @@ extern tree build_vec_init (tree, tree, tree, int); ...@@ -3924,7 +3932,6 @@ extern tree build_vec_init (tree, tree, tree, int);
extern tree build_x_delete (tree, int, tree); extern tree build_x_delete (tree, int, tree);
extern tree build_delete (tree, tree, special_function_kind, int, int); extern tree build_delete (tree, tree, special_function_kind, int, int);
extern void push_base_cleanups (void); extern void push_base_cleanups (void);
extern tree build_vbase_delete (tree, tree);
extern tree build_vec_delete (tree, tree, special_function_kind, int); extern tree build_vec_delete (tree, tree, special_function_kind, int);
extern tree create_temporary_var (tree); extern tree create_temporary_var (tree);
extern void initialize_vtbl_ptrs (tree); extern void initialize_vtbl_ptrs (tree);
......
...@@ -793,6 +793,11 @@ convert_to_void (tree expr, const char *implicit) ...@@ -793,6 +793,11 @@ convert_to_void (tree expr, const char *implicit)
return expr; return expr;
if (invalid_nonstatic_memfn_p (expr)) if (invalid_nonstatic_memfn_p (expr))
return error_mark_node; return error_mark_node;
if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
{
error ("pseudo-destructor is not called");
return error_mark_node;
}
if (VOID_TYPE_P (TREE_TYPE (expr))) if (VOID_TYPE_P (TREE_TYPE (expr)))
return expr; return expr;
switch (TREE_CODE (expr)) switch (TREE_CODE (expr))
......
...@@ -10929,9 +10929,6 @@ cxx_maybe_build_cleanup (tree decl) ...@@ -10929,9 +10929,6 @@ cxx_maybe_build_cleanup (tree decl)
rval = build_delete (TREE_TYPE (rval), rval, rval = build_delete (TREE_TYPE (rval), rval,
sfk_complete_destructor, flags, 0); sfk_complete_destructor, flags, 0);
if (has_vbases && !TYPE_HAS_DESTRUCTOR (type))
rval = build_compound_expr (rval, build_vbase_delete (type, decl));
return rval; return rval;
} }
return NULL_TREE; return NULL_TREE;
......
...@@ -182,9 +182,12 @@ dtor_nothrow (tree type) ...@@ -182,9 +182,12 @@ dtor_nothrow (tree type)
if (type == NULL_TREE) if (type == NULL_TREE)
return 0; return 0;
if (! TYPE_HAS_DESTRUCTOR (type)) if (!CLASS_TYPE_P (type))
return 1; return 1;
if (CLASSTYPE_LAZY_DESTRUCTOR (type))
lazily_declare_fn (sfk_destructor, type);
return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type)); return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
} }
...@@ -709,7 +712,7 @@ build_throw (tree exp) ...@@ -709,7 +712,7 @@ build_throw (tree exp)
throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object))); throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object))) if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
{ {
cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
complete_dtor_identifier, 0); complete_dtor_identifier, 0);
......
...@@ -2796,7 +2796,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, ...@@ -2796,7 +2796,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
tree do_delete = NULL_TREE; tree do_delete = NULL_TREE;
tree ifexp; tree ifexp;
gcc_assert (TYPE_HAS_DESTRUCTOR (type)); if (CLASSTYPE_LAZY_DESTRUCTOR (type))
lazily_declare_fn (sfk_destructor, type);
/* For `::delete x', we must not use the deleting destructor /* For `::delete x', we must not use the deleting destructor
since then we would not be sure to get the global `operator since then we would not be sure to get the global `operator
...@@ -2935,34 +2936,6 @@ push_base_cleanups (void) ...@@ -2935,34 +2936,6 @@ push_base_cleanups (void)
} }
} }
/* For type TYPE, delete the virtual baseclass objects of DECL. */
tree
build_vbase_delete (tree type, tree decl)
{
unsigned ix;
tree binfo;
tree result;
VEC (tree) *vbases;
tree addr = build_unary_op (ADDR_EXPR, decl, 0);
gcc_assert (addr != error_mark_node);
result = convert_to_void (integer_zero_node, NULL);
for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0;
VEC_iterate (tree, vbases, ix, binfo); ix++)
{
tree base_addr = convert_force
(build_pointer_type (BINFO_TYPE (binfo)), addr, 0);
tree base_delete = build_delete
(TREE_TYPE (base_addr), base_addr, sfk_base_destructor,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
result = build_compound_expr (result, base_delete);
}
return result;
}
/* Build a C++ vector delete expression. /* Build a C++ vector delete expression.
MAXINDEX is the number of elements to be deleted. MAXINDEX is the number of elements to be deleted.
ELT_SIZE is the nominal size of each element in the vector. ELT_SIZE is the nominal size of each element in the vector.
......
...@@ -823,9 +823,7 @@ synthesize_exception_spec (tree type, tree (*extractor) (tree, void*), ...@@ -823,9 +823,7 @@ synthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
static tree static tree
locate_dtor (tree type, void *client ATTRIBUTE_UNUSED) locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
{ {
return (CLASSTYPE_METHOD_VEC (type) return CLASSTYPE_DESTRUCTORS (type);
? CLASSTYPE_DESTRUCTORS (type)
: NULL_TREE);
} }
/* Locate the default ctor of TYPE. */ /* Locate the default ctor of TYPE. */
...@@ -1035,7 +1033,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) ...@@ -1035,7 +1033,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
DECL_DECLARED_INLINE_P (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1;
DECL_INLINE (fn) = 1; DECL_INLINE (fn) = 1;
gcc_assert (!TREE_USED (fn)); gcc_assert (!TREE_USED (fn));
return fn; return fn;
} }
...@@ -1060,24 +1058,46 @@ lazily_declare_fn (special_function_kind sfk, tree type) ...@@ -1060,24 +1058,46 @@ lazily_declare_fn (special_function_kind sfk, tree type)
const_p = false; const_p = false;
/* Declare the function. */ /* Declare the function. */
fn = implicitly_declare_fn (sfk, type, const_p); fn = implicitly_declare_fn (sfk, type, const_p);
/* A destructor may be virtual. */
if (sfk == sfk_destructor)
check_for_override (fn, type);
/* Add it to CLASSTYPE_METHOD_VEC. */ /* Add it to CLASSTYPE_METHOD_VEC. */
add_method (type, fn); add_method (type, fn);
/* Add it to TYPE_METHODS. */ /* Add it to TYPE_METHODS. */
TREE_CHAIN (fn) = TYPE_METHODS (type); if (sfk == sfk_destructor
TYPE_METHODS (type) = fn; && DECL_VIRTUAL_P (fn)
&& abi_version_at_least (2))
/* The ABI requires that a virtual destructor go at the end of the
vtable. */
TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn);
else
{
/* G++ 3.2 put the implicit destructor at the *beginning* of the
TYPE_METHODS list, which cause the destructor to be emitted
in an incorrect location in the vtable. */
if (warn_abi && DECL_VIRTUAL_P (fn))
warning ("vtable layout for class %qT may not be ABI-compliant"
"and may change in a future version of GCC due to "
"implicit virtual destructor",
type);
TREE_CHAIN (fn) = TYPE_METHODS (type);
TYPE_METHODS (type) = fn;
}
maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0); maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0);
if (sfk == sfk_constructor || sfk == sfk_copy_constructor) if (sfk == sfk_assignment_operator)
CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0;
else
{ {
/* Remember that the function has been created. */ /* Remember that the function has been created. */
if (sfk == sfk_constructor) if (sfk == sfk_constructor)
CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0; CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0;
else else if (sfk == sfk_copy_constructor)
CLASSTYPE_LAZY_COPY_CTOR (type) = 0; CLASSTYPE_LAZY_COPY_CTOR (type) = 0;
else if (sfk == sfk_destructor)
CLASSTYPE_LAZY_DESTRUCTOR (type) = 0;
/* Create appropriate clones. */ /* Create appropriate clones. */
clone_function_decl (fn, /*update_method_vec=*/true); clone_function_decl (fn, /*update_method_vec=*/true);
} }
else if (sfk == sfk_assignment_operator)
CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0;
return fn; return fn;
} }
......
...@@ -14252,6 +14252,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name, ...@@ -14252,6 +14252,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
/* If that's not a class type, there is no destructor. */ /* If that's not a class type, there is no destructor. */
if (!type || !CLASS_TYPE_P (type)) if (!type || !CLASS_TYPE_P (type))
return error_mark_node; return error_mark_node;
if (CLASSTYPE_LAZY_DESTRUCTOR (type))
lazily_declare_fn (sfk_destructor, type);
if (!CLASSTYPE_DESTRUCTORS (type)) if (!CLASSTYPE_DESTRUCTORS (type))
return error_mark_node; return error_mark_node;
/* If it was a class type, return the destructor. */ /* If it was a class type, return the destructor. */
......
...@@ -1932,7 +1932,7 @@ check_explicit_specialization (tree declarator, ...@@ -1932,7 +1932,7 @@ check_explicit_specialization (tree declarator,
int is_constructor = DECL_CONSTRUCTOR_P (decl); int is_constructor = DECL_CONSTRUCTOR_P (decl);
if (is_constructor ? !TYPE_HAS_CONSTRUCTOR (ctype) if (is_constructor ? !TYPE_HAS_CONSTRUCTOR (ctype)
: !TYPE_HAS_DESTRUCTOR (ctype)) : !CLASSTYPE_DESTRUCTORS (ctype))
{ {
/* From [temp.expl.spec]: /* From [temp.expl.spec]:
...@@ -5541,7 +5541,6 @@ instantiate_class_template (tree type) ...@@ -5541,7 +5541,6 @@ instantiate_class_template (tree type)
input_location = DECL_SOURCE_LOCATION (TYPE_NAME (pattern)); input_location = DECL_SOURCE_LOCATION (TYPE_NAME (pattern));
TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern); TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern); TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern); TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern); TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
......
...@@ -100,8 +100,6 @@ cxx_print_type (FILE *file, tree node, int indent) ...@@ -100,8 +100,6 @@ cxx_print_type (FILE *file, tree node, int indent)
fputs ( "needs-constructor", file); fputs ( "needs-constructor", file);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node)) if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node))
fputs (" needs-destructor", file); fputs (" needs-destructor", file);
if (TYPE_HAS_DESTRUCTOR (node))
fputs (" ~X()", file);
if (TYPE_HAS_DEFAULT_CONSTRUCTOR (node)) if (TYPE_HAS_DEFAULT_CONSTRUCTOR (node))
fputs (" X()", file); fputs (" X()", file);
if (TYPE_HAS_CONVERSION (node)) if (TYPE_HAS_CONVERSION (node))
......
...@@ -1342,7 +1342,7 @@ emit_support_tinfos (void) ...@@ -1342,7 +1342,7 @@ emit_support_tinfos (void)
if (!COMPLETE_TYPE_P (bltn_type)) if (!COMPLETE_TYPE_P (bltn_type))
return; return;
dtor = CLASSTYPE_DESTRUCTORS (bltn_type); dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
if (DECL_EXTERNAL (dtor)) if (!dtor || DECL_EXTERNAL (dtor))
return; return;
doing_runtime = 1; doing_runtime = 1;
for (ix = 0; fundamentals[ix]; ix++) for (ix = 0; fundamentals[ix]; ix++)
......
...@@ -1367,6 +1367,12 @@ lookup_fnfields_1 (tree type, tree name) ...@@ -1367,6 +1367,12 @@ lookup_fnfields_1 (tree type, tree name)
else if (name == ansi_assopname(NOP_EXPR) else if (name == ansi_assopname(NOP_EXPR)
&& CLASSTYPE_LAZY_ASSIGNMENT_OP (type)) && CLASSTYPE_LAZY_ASSIGNMENT_OP (type))
lazily_declare_fn (sfk_assignment_operator, type); lazily_declare_fn (sfk_assignment_operator, type);
else if ((name == dtor_identifier
|| name == base_dtor_identifier
|| name == complete_dtor_identifier
|| name == deleting_dtor_identifier)
&& CLASSTYPE_LAZY_DESTRUCTOR (type))
lazily_declare_fn (sfk_destructor, type);
} }
method_vec = CLASSTYPE_METHOD_VEC (type); method_vec = CLASSTYPE_METHOD_VEC (type);
......
...@@ -1577,9 +1577,6 @@ build_class_member_access_expr (tree object, tree member, ...@@ -1577,9 +1577,6 @@ build_class_member_access_expr (tree object, tree member,
if (object == error_mark_node || member == error_mark_node) if (object == error_mark_node || member == error_mark_node)
return error_mark_node; return error_mark_node;
if (TREE_CODE (member) == PSEUDO_DTOR_EXPR)
return member;
gcc_assert (DECL_P (member) || BASELINK_P (member)); gcc_assert (DECL_P (member) || BASELINK_P (member));
/* [expr.ref] /* [expr.ref]
...@@ -1822,9 +1819,6 @@ lookup_destructor (tree object, tree scope, tree dtor_name) ...@@ -1822,9 +1819,6 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
TYPE_MAIN_VARIANT (object_type), dtor_type); TYPE_MAIN_VARIANT (object_type), dtor_type);
return error_mark_node; return error_mark_node;
} }
if (!TYPE_HAS_DESTRUCTOR (dtor_type))
return build3 (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
dtor_type);
expr = lookup_member (dtor_type, complete_dtor_identifier, expr = lookup_member (dtor_type, complete_dtor_identifier,
/*protect=*/1, /*want_type=*/false); /*protect=*/1, /*want_type=*/false);
expr = (adjust_result_of_qualified_name_lookup expr = (adjust_result_of_qualified_name_lookup
......
2005-02-08 Mark Mitchell <mark@codesourcery.com>
PR c++/19733
* g++.dg/parse/crash23.C: New test.
* g++.dg/warn/Weff1.C: New test.
2005-02-09 Joseph S. Myers <joseph@codesourcery.com> 2005-02-09 Joseph S. Myers <joseph@codesourcery.com>
* gcc.dg/20050209-1.c: New test. * gcc.dg/20050209-1.c: New test.
......
// PR c++/19733
struct A {};
typedef int I;
void foo() {
A().~A; // { dg-error "" }
A().A::~A; // { dg-error "" }
(int().I::~I, 3); // { dg-error "" }
int().I::~I; // { dg-error "" }
}
// { dg-options "-Weffc++" }
struct S {};
/* Base classes should have virtual destructors. */
struct T : public S {}; // { dg-warning "" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment