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
This commit is contained in:
parent
ec2cd8b20c
commit
9f4faeaee1
@ -1,3 +1,51 @@
|
|||||||
|
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
|
||||||
|
156
gcc/cp/class.c
156
gcc/cp/class.c
@ -116,7 +116,6 @@ static void modify_vtable_entry (tree, tree, tree, tree, tree *);
|
|||||||
static void finish_struct_bits (tree);
|
static void finish_struct_bits (tree);
|
||||||
static int alter_access (tree, tree, tree);
|
static int alter_access (tree, tree, tree);
|
||||||
static void handle_using_decl (tree, tree);
|
static void handle_using_decl (tree, tree);
|
||||||
static void check_for_override (tree, tree);
|
|
||||||
static tree dfs_modify_vtables (tree, void *);
|
static tree dfs_modify_vtables (tree, void *);
|
||||||
static tree modify_all_vtables (tree, tree);
|
static tree modify_all_vtables (tree, tree);
|
||||||
static void determine_primary_bases (tree);
|
static void determine_primary_bases (tree);
|
||||||
@ -893,13 +892,16 @@ add_method (tree type, tree method)
|
|||||||
else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
|
else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
|
||||||
{
|
{
|
||||||
slot = CLASSTYPE_DESTRUCTOR_SLOT;
|
slot = CLASSTYPE_DESTRUCTOR_SLOT;
|
||||||
TYPE_HAS_DESTRUCTOR (type) = 1;
|
|
||||||
|
|
||||||
if (TYPE_FOR_JAVA (type))
|
if (TYPE_FOR_JAVA (type))
|
||||||
error (DECL_ARTIFICIAL (method)
|
{
|
||||||
? "Java class %qT cannot have an implicit non-trivial destructor"
|
if (!DECL_ARTIFICIAL (method))
|
||||||
: "Java class %qT cannot have a destructor",
|
error ("Java class %qT cannot have a destructor", type);
|
||||||
DECL_CONTEXT (method));
|
else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||||
|
error ("Java class %qT cannot have an implicit non-trivial "
|
||||||
|
"destructor",
|
||||||
|
type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1203,8 +1205,7 @@ check_bases (tree t,
|
|||||||
/* Effective C++ rule 14. We only need to check TYPE_POLYMORPHIC_P
|
/* Effective C++ rule 14. We only need to check TYPE_POLYMORPHIC_P
|
||||||
here because the case of virtual functions but non-virtual
|
here because the case of virtual functions but non-virtual
|
||||||
dtor is handled in finish_struct_1. */
|
dtor is handled in finish_struct_1. */
|
||||||
if (warn_ecpp && ! TYPE_POLYMORPHIC_P (basetype)
|
if (warn_ecpp && ! TYPE_POLYMORPHIC_P (basetype))
|
||||||
&& TYPE_HAS_DESTRUCTOR (basetype))
|
|
||||||
warning ("base class %q#T has a non-virtual destructor", basetype);
|
warning ("base class %q#T has a non-virtual destructor", basetype);
|
||||||
|
|
||||||
/* If the base class doesn't have copy constructors or
|
/* If the base class doesn't have copy constructors or
|
||||||
@ -1406,7 +1407,6 @@ finish_struct_bits (tree t)
|
|||||||
/* These fields are in the _TYPE part of the node, not in
|
/* These fields are in the _TYPE part of the node, not in
|
||||||
the TYPE_LANG_SPECIFIC component, so they are not shared. */
|
the TYPE_LANG_SPECIFIC component, so they are not shared. */
|
||||||
TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
|
TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
|
||||||
TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);
|
|
||||||
TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
|
TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
|
||||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)
|
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)
|
||||||
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
|
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
|
||||||
@ -1540,8 +1540,8 @@ maybe_warn_about_overly_private_class (tree t)
|
|||||||
/* Even if some of the member functions are non-private, the class
|
/* Even if some of the member functions are non-private, the class
|
||||||
won't be useful for much if all the constructors or destructors
|
won't be useful for much if all the constructors or destructors
|
||||||
are private: such an object can never be created or destroyed. */
|
are private: such an object can never be created or destroyed. */
|
||||||
if (TYPE_HAS_DESTRUCTOR (t)
|
fn = CLASSTYPE_DESTRUCTORS (t);
|
||||||
&& TREE_PRIVATE (CLASSTYPE_DESTRUCTORS (t)))
|
if (fn && TREE_PRIVATE (fn))
|
||||||
{
|
{
|
||||||
warning ("%q#T only defines a private destructor and has no friends",
|
warning ("%q#T only defines a private destructor and has no friends",
|
||||||
t);
|
t);
|
||||||
@ -1693,11 +1693,6 @@ finish_struct_methods (tree t)
|
|||||||
fn_fields = TREE_CHAIN (fn_fields))
|
fn_fields = TREE_CHAIN (fn_fields))
|
||||||
DECL_IN_AGGR_P (fn_fields) = 0;
|
DECL_IN_AGGR_P (fn_fields) = 0;
|
||||||
|
|
||||||
if (TYPE_HAS_DESTRUCTOR (t) && !CLASSTYPE_DESTRUCTORS (t))
|
|
||||||
/* We thought there was a destructor, but there wasn't. Some
|
|
||||||
parse errors cause this anomalous situation. */
|
|
||||||
TYPE_HAS_DESTRUCTOR (t) = 0;
|
|
||||||
|
|
||||||
/* Issue warnings about private constructors and such. If there are
|
/* Issue warnings about private constructors and such. If there are
|
||||||
no methods, then some public defaults are generated. */
|
no methods, then some public defaults are generated. */
|
||||||
maybe_warn_about_overly_private_class (t);
|
maybe_warn_about_overly_private_class (t);
|
||||||
@ -2284,7 +2279,7 @@ get_basefndecls (tree name, tree t)
|
|||||||
a method declared virtual in the base class, then
|
a method declared virtual in the base class, then
|
||||||
mark this field as being virtual as well. */
|
mark this field as being virtual as well. */
|
||||||
|
|
||||||
static void
|
void
|
||||||
check_for_override (tree decl, tree ctype)
|
check_for_override (tree decl, tree ctype)
|
||||||
{
|
{
|
||||||
if (TREE_CODE (decl) == TEMPLATE_DECL)
|
if (TREE_CODE (decl) == TEMPLATE_DECL)
|
||||||
@ -2465,8 +2460,7 @@ maybe_add_class_template_decl_list (tree type, tree t, int friend_p)
|
|||||||
CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, the
|
CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, the
|
||||||
class cannot have a default constructor, copy constructor taking a
|
class cannot have a default constructor, copy constructor taking a
|
||||||
const reference argument, or an assignment operator taking a const
|
const reference argument, or an assignment operator taking a const
|
||||||
reference, respectively. If a virtual destructor is created, its
|
reference, respectively. */
|
||||||
DECL is returned; otherwise the return value is NULL_TREE. */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_implicitly_declared_members (tree t,
|
add_implicitly_declared_members (tree t,
|
||||||
@ -2474,26 +2468,53 @@ add_implicitly_declared_members (tree t,
|
|||||||
int cant_have_const_cctor,
|
int cant_have_const_cctor,
|
||||||
int cant_have_const_assignment)
|
int cant_have_const_assignment)
|
||||||
{
|
{
|
||||||
tree default_fn;
|
|
||||||
tree implicit_fns = NULL_TREE;
|
|
||||||
tree virtual_dtor = NULL_TREE;
|
|
||||||
tree *f;
|
|
||||||
|
|
||||||
/* Destructor. */
|
/* Destructor. */
|
||||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
|
if (!CLASSTYPE_DESTRUCTORS (t))
|
||||||
{
|
{
|
||||||
default_fn = implicitly_declare_fn (sfk_destructor, t, /*const_p=*/0);
|
/* In general, we create destructors lazily. */
|
||||||
check_for_override (default_fn, t);
|
CLASSTYPE_LAZY_DESTRUCTOR (t) = 1;
|
||||||
|
/* However, if the implicit destructor is non-trivial
|
||||||
|
destructor, we sometimes have to create it at this point. */
|
||||||
|
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
|
||||||
|
{
|
||||||
|
bool lazy_p = true;
|
||||||
|
|
||||||
TREE_CHAIN (default_fn) = implicit_fns;
|
if (TYPE_FOR_JAVA (t))
|
||||||
implicit_fns = default_fn;
|
/* If this a Java class, any non-trivial destructor is
|
||||||
|
invalid, even if compiler-generated. Therefore, if the
|
||||||
if (DECL_VINDEX (default_fn))
|
destructor is non-trivial we create it now. */
|
||||||
virtual_dtor = default_fn;
|
lazy_p = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tree binfo;
|
||||||
|
tree base_binfo;
|
||||||
|
int ix;
|
||||||
|
|
||||||
|
/* If the implicit destructor will be virtual, then we must
|
||||||
|
generate it now because (unfortunately) we do not
|
||||||
|
generate virtual tables lazily. */
|
||||||
|
binfo = TYPE_BINFO (t);
|
||||||
|
for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
|
||||||
|
{
|
||||||
|
tree base_type;
|
||||||
|
tree dtor;
|
||||||
|
|
||||||
|
base_type = BINFO_TYPE (base_binfo);
|
||||||
|
dtor = CLASSTYPE_DESTRUCTORS (base_type);
|
||||||
|
if (dtor && DECL_VIRTUAL_P (dtor))
|
||||||
|
{
|
||||||
|
lazy_p = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we can't get away with being lazy, generate the destructor
|
||||||
|
now. */
|
||||||
|
if (!lazy_p)
|
||||||
|
lazily_declare_fn (sfk_destructor, t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
/* Any non-implicit destructor is non-trivial. */
|
|
||||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
|
|
||||||
|
|
||||||
/* Default constructor. */
|
/* Default constructor. */
|
||||||
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
|
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
|
||||||
@ -2521,29 +2542,6 @@ add_implicitly_declared_members (tree t,
|
|||||||
TYPE_HAS_CONST_ASSIGN_REF (t) = !cant_have_const_assignment;
|
TYPE_HAS_CONST_ASSIGN_REF (t) = !cant_have_const_assignment;
|
||||||
CLASSTYPE_LAZY_ASSIGNMENT_OP (t) = 1;
|
CLASSTYPE_LAZY_ASSIGNMENT_OP (t) = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now, hook all of the new functions on to TYPE_METHODS,
|
|
||||||
and add them to the CLASSTYPE_METHOD_VEC. */
|
|
||||||
for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
|
|
||||||
{
|
|
||||||
add_method (t, *f);
|
|
||||||
maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
|
|
||||||
}
|
|
||||||
if (abi_version_at_least (2))
|
|
||||||
/* G++ 3.2 put the implicit destructor at the *beginning* of the
|
|
||||||
list, which cause the destructor to be emitted in an incorrect
|
|
||||||
location in the vtable. */
|
|
||||||
TYPE_METHODS (t) = chainon (TYPE_METHODS (t), implicit_fns);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (warn_abi && virtual_dtor)
|
|
||||||
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",
|
|
||||||
t);
|
|
||||||
*f = TYPE_METHODS (t);
|
|
||||||
TYPE_METHODS (t) = implicit_fns;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subroutine of finish_struct_1. Recursively count the number of fields
|
/* Subroutine of finish_struct_1. Recursively count the number of fields
|
||||||
@ -3012,7 +3010,7 @@ check_field_decls (tree t, tree *access_decls,
|
|||||||
if (warn_ecpp
|
if (warn_ecpp
|
||||||
&& has_pointers
|
&& has_pointers
|
||||||
&& TYPE_HAS_CONSTRUCTOR (t)
|
&& TYPE_HAS_CONSTRUCTOR (t)
|
||||||
&& TYPE_HAS_DESTRUCTOR (t)
|
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|
||||||
&& !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
|
&& !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
|
||||||
{
|
{
|
||||||
warning ("%q#T has pointer data members", t);
|
warning ("%q#T has pointer data members", t);
|
||||||
@ -3660,6 +3658,9 @@ check_methods (tree t)
|
|||||||
if (DECL_PURE_VIRTUAL_P (x))
|
if (DECL_PURE_VIRTUAL_P (x))
|
||||||
VEC_safe_push (tree, CLASSTYPE_PURE_VIRTUALS (t), x);
|
VEC_safe_push (tree, CLASSTYPE_PURE_VIRTUALS (t), x);
|
||||||
}
|
}
|
||||||
|
/* All user-declared destructors are non-trivial. */
|
||||||
|
if (DECL_DESTRUCTOR_P (x))
|
||||||
|
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4034,15 +4035,18 @@ check_bases_and_members (tree t)
|
|||||||
check_bases (t, &cant_have_default_ctor, &cant_have_const_ctor,
|
check_bases (t, &cant_have_default_ctor, &cant_have_const_ctor,
|
||||||
&no_const_asn_ref);
|
&no_const_asn_ref);
|
||||||
|
|
||||||
/* Check all the data member declarations. */
|
/* Check all the method declarations. */
|
||||||
|
check_methods (t);
|
||||||
|
|
||||||
|
/* Check all the data member declarations. We cannot call
|
||||||
|
check_field_decls until we have called check_bases check_methods,
|
||||||
|
as check_field_decls depends on TYPE_HAS_NONTRIVIAL_DESTRUCTOR
|
||||||
|
being set appropriately. */
|
||||||
check_field_decls (t, &access_decls,
|
check_field_decls (t, &access_decls,
|
||||||
&cant_have_default_ctor,
|
&cant_have_default_ctor,
|
||||||
&cant_have_const_ctor,
|
&cant_have_const_ctor,
|
||||||
&no_const_asn_ref);
|
&no_const_asn_ref);
|
||||||
|
|
||||||
/* Check all the method declarations. */
|
|
||||||
check_methods (t);
|
|
||||||
|
|
||||||
/* A nearly-empty class has to be vptr-containing; a nearly empty
|
/* A nearly-empty class has to be vptr-containing; a nearly empty
|
||||||
class contains just a vptr. */
|
class contains just a vptr. */
|
||||||
if (!TYPE_CONTAINS_VPTR_P (t))
|
if (!TYPE_CONTAINS_VPTR_P (t))
|
||||||
@ -4057,7 +4061,8 @@ check_bases_and_members (tree t)
|
|||||||
CLASSTYPE_NON_AGGREGATE (t)
|
CLASSTYPE_NON_AGGREGATE (t)
|
||||||
|= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_POLYMORPHIC_P (t));
|
|= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_POLYMORPHIC_P (t));
|
||||||
CLASSTYPE_NON_POD_P (t)
|
CLASSTYPE_NON_POD_P (t)
|
||||||
|= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t)
|
|= (CLASSTYPE_NON_AGGREGATE (t)
|
||||||
|
|| TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|
||||||
|| TYPE_HAS_ASSIGN_REF (t));
|
|| TYPE_HAS_ASSIGN_REF (t));
|
||||||
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|
||||||
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
|
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
|
||||||
@ -5007,17 +5012,22 @@ finish_struct_1 (tree t)
|
|||||||
/* Build the VTT for T. */
|
/* Build the VTT for T. */
|
||||||
build_vtt (t);
|
build_vtt (t);
|
||||||
|
|
||||||
if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t) && TYPE_HAS_DESTRUCTOR (t)
|
if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t))
|
||||||
&& !DECL_VINDEX (CLASSTYPE_DESTRUCTORS (t)))
|
|
||||||
|
|
||||||
{
|
{
|
||||||
tree dtor = CLASSTYPE_DESTRUCTORS (t);
|
tree dtor;
|
||||||
|
|
||||||
/* Warn only if the dtor is non-private or the class has friends */
|
dtor = CLASSTYPE_DESTRUCTORS (t);
|
||||||
if (!TREE_PRIVATE (dtor) ||
|
/* Warn only if the dtor is non-private or the class has
|
||||||
(CLASSTYPE_FRIEND_CLASSES (t) ||
|
friends. */
|
||||||
DECL_FRIENDLIST (TYPE_MAIN_DECL (t))))
|
if (/* An implicitly declared destructor is always public. And,
|
||||||
warning ("%q#T has virtual functions but non-virtual destructor", t);
|
if it were virtual, we would have created it by now. */
|
||||||
|
!dtor
|
||||||
|
|| (!DECL_VINDEX (dtor)
|
||||||
|
&& (!TREE_PRIVATE (dtor)
|
||||||
|
|| CLASSTYPE_FRIEND_CLASSES (t)
|
||||||
|
|| DECL_FRIENDLIST (TYPE_MAIN_DECL (t)))))
|
||||||
|
warning ("%q#T has virtual functions but non-virtual destructor",
|
||||||
|
t);
|
||||||
}
|
}
|
||||||
|
|
||||||
complete_vars (t);
|
complete_vars (t);
|
||||||
|
@ -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)
|
|||||||
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;
|
|||||||
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(())
|
|||||||
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(())
|
|||||||
/* 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(())
|
|||||||
#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(())
|
|||||||
(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(())
|
|||||||
&& 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);
|
|||||||
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);
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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*),
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
/* 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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
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.
|
||||||
|
12
gcc/testsuite/g++.dg/parse/crash23.C
Normal file
12
gcc/testsuite/g++.dg/parse/crash23.C
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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 "" }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
5
gcc/testsuite/g++.dg/warn/Weff1.C
Normal file
5
gcc/testsuite/g++.dg/warn/Weff1.C
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// { dg-options "-Weffc++" }
|
||||||
|
|
||||||
|
struct S {};
|
||||||
|
/* Base classes should have virtual destructors. */
|
||||||
|
struct T : public S {}; // { dg-warning "" }
|
Loading…
Reference in New Issue
Block a user