Commit 1c2c08a5 by Jason Merrill Committed by Jason Merrill

method.c (hack_identifier): Don't let a class template out.

	* method.c (hack_identifier): Don't let a class template out.
	* call.c (check_dtor_name): Split out.
	(build_scoped_method_call): Use it.
	(build_method_call): Use it.
	* init.c (build_offset_ref): Use it.
	* typeck.c (build_static_cast): Fix handling of pointers to members.
	* decl.c (finish_function): Just return nothing from a constructor.
	* typeck.c (c_expand_return): Complain about returning a void
	expression from a destructor.

From-SVN: r20521
parent 8b45da67
1998-06-16 Jason Merrill <jason@yorick.cygnus.com>
* method.c (hack_identifier): Don't let a class template out.
* call.c (check_dtor_name): Split out.
(build_scoped_method_call): Use it.
(build_method_call): Use it.
* init.c (build_offset_ref): Use it.
* typeck.c (build_static_cast): Fix handling of pointers to members.
* decl.c (finish_function): Just return nothing from a constructor.
* typeck.c (c_expand_return): Complain about returning a void
expression from a destructor.
1998-06-13 Mark Mitchell <mark@markmitchell.com> 1998-06-13 Mark Mitchell <mark@markmitchell.com>
* class.c (alter_access): Accept a BINFO explaining how to get * class.c (alter_access): Accept a BINFO explaining how to get
......
...@@ -340,6 +340,35 @@ resolve_scope_to_name (outer_type, inner_stuff) ...@@ -340,6 +340,35 @@ resolve_scope_to_name (outer_type, inner_stuff)
return tmp; return tmp;
} }
/* Returns nonzero iff the destructor name specified in NAME
(a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many
forms... */
int
check_dtor_name (basetype, name)
tree basetype, name;
{
name = TREE_OPERAND (name, 0);
if (TREE_CODE (name) == TYPE_DECL)
name = TREE_TYPE (name);
else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
/* OK */;
else if (TREE_CODE (name) == IDENTIFIER_NODE)
{
if (IS_AGGR_TYPE (basetype) && name == constructor_name (basetype))
name = basetype;
else
name = get_type_value (name);
}
else
my_friendly_abort (980605);
if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name))
return 1;
return 0;
}
/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'. /* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
This is how virtual function calls are avoided. */ This is how virtual function calls are avoided. */
...@@ -386,31 +415,9 @@ build_scoped_method_call (exp, basetype, name, parms) ...@@ -386,31 +415,9 @@ build_scoped_method_call (exp, basetype, name, parms)
binfo = NULL_TREE; binfo = NULL_TREE;
/* Check the destructor call syntax. */ /* Check the destructor call syntax. */
if (TREE_CODE (name) == BIT_NOT_EXPR) if (TREE_CODE (name) == BIT_NOT_EXPR && ! check_dtor_name (basetype, name))
{
tmp = TREE_OPERAND (name, 0);
if (TREE_CODE (tmp) == TYPE_DECL)
tmp = TREE_TYPE (tmp);
else if (TREE_CODE_CLASS (TREE_CODE (tmp)) == 't')
/* OK */;
else if (TREE_CODE (tmp) == IDENTIFIER_NODE)
{
if (IS_AGGR_TYPE (basetype) && tmp == constructor_name (basetype))
tmp = basetype;
else
tmp = get_type_value (tmp);
}
else
my_friendly_abort (980605);
if (! (tmp && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (tmp)))
{
cp_error ("qualified type `%T' does not match destructor name `~%T'", cp_error ("qualified type `%T' does not match destructor name `~%T'",
basetype, TREE_OPERAND (name, 0)); basetype, TREE_OPERAND (name, 0));
return error_mark_node;
}
}
/* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
that explicit ~int is caught in the parser; this deals with typedefs that explicit ~int is caught in the parser; this deals with typedefs
...@@ -645,36 +652,16 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -645,36 +652,16 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (TREE_CODE (name) == BIT_NOT_EXPR) if (TREE_CODE (name) == BIT_NOT_EXPR)
{ {
tree tmp;
tmp = name = TREE_OPERAND (name, 0);
if (parms) if (parms)
error ("destructors take no parameters"); error ("destructors take no parameters");
basetype = TREE_TYPE (instance); basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE) if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype); basetype = TREE_TYPE (basetype);
if (TREE_CODE (tmp) == TYPE_DECL) if (! check_dtor_name (basetype, name))
tmp = TREE_TYPE (tmp); cp_error
else if (TREE_CODE_CLASS (TREE_CODE (tmp)) == 't') ("destructor name `~%T' does not match type `%T' of expression",
/* OK */; TREE_OPERAND (name, 0), basetype);
else if (TREE_CODE (tmp) == IDENTIFIER_NODE)
{
if (IS_AGGR_TYPE (basetype) && tmp == constructor_name (basetype))
tmp = basetype;
else
tmp = get_type_value (tmp);
}
else
my_friendly_abort (980605);
if (! (tmp && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (tmp)))
{
cp_error ("destructor name `~%T' does not match type `%T' of expression",
name, basetype);
return cp_convert (void_type_node, instance);
}
if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype))) if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
return cp_convert (void_type_node, instance); return cp_convert (void_type_node, instance);
......
...@@ -12599,7 +12599,8 @@ finish_function (lineno, call_poplevel, nested) ...@@ -12599,7 +12599,8 @@ finish_function (lineno, call_poplevel, nested)
expand_end_bindings (decls, decls != NULL_TREE, 0); expand_end_bindings (decls, decls != NULL_TREE, 0);
poplevel (decls != NULL_TREE, 0, 0); poplevel (decls != NULL_TREE, 0, 0);
} }
c_expand_return (current_class_ptr); /* c_expand_return knows to return 'this' from a constructor. */
c_expand_return (NULL_TREE);
} }
else if (TREE_CODE (TREE_TYPE (DECL_RESULT (current_function_decl))) != VOID_TYPE else if (TREE_CODE (TREE_TYPE (DECL_RESULT (current_function_decl))) != VOID_TYPE
&& return_label != NULL_RTX) && return_label != NULL_RTX)
...@@ -12666,7 +12667,8 @@ finish_function (lineno, call_poplevel, nested) ...@@ -12666,7 +12667,8 @@ finish_function (lineno, call_poplevel, nested)
poplevel (decls != NULL_TREE, 1, 0); poplevel (decls != NULL_TREE, 1, 0);
} }
c_expand_return (current_class_ptr); /* c_expand_return knows to return 'this' from a constructor. */
c_expand_return (NULL_TREE);
current_function_assigns_this = 0; current_function_assigns_this = 0;
current_function_just_assigned_this = 0; current_function_just_assigned_this = 0;
......
...@@ -1521,7 +1521,6 @@ build_offset_ref (type, name) ...@@ -1521,7 +1521,6 @@ build_offset_ref (type, name)
{ {
tree decl, fnfields, fields, t = error_mark_node; tree decl, fnfields, fields, t = error_mark_node;
tree basebinfo = NULL_TREE; tree basebinfo = NULL_TREE;
int dtor = 0;
tree orig_name = name; tree orig_name = name;
/* class templates can come in as TEMPLATE_DECLs here. */ /* class templates can come in as TEMPLATE_DECLs here. */
...@@ -1553,12 +1552,17 @@ build_offset_ref (type, name) ...@@ -1553,12 +1552,17 @@ build_offset_ref (type, name)
if (TREE_CODE (name) == BIT_NOT_EXPR) if (TREE_CODE (name) == BIT_NOT_EXPR)
{ {
dtor = 1; if (! check_dtor_name (type, name))
name = TREE_OPERAND (name, 0); cp_error ("qualified type `%T' does not match destructor name `~%T'",
type, TREE_OPERAND (name, 0));
name = dtor_identifier;
} }
#if 0
if (name == constructor_name_full (type)) /* I think this is wrong, but the draft is unclear. --jason 6/15/98 */
name = constructor_name (type); else if (name == constructor_name_full (type)
|| name == constructor_name (type))
name = ctor_identifier;
#endif
if (TYPE_SIZE (complete_type (type)) == 0) if (TYPE_SIZE (complete_type (type)) == 0)
{ {
...@@ -1598,18 +1602,6 @@ build_offset_ref (type, name) ...@@ -1598,18 +1602,6 @@ build_offset_ref (type, name)
else else
decl = current_class_ref; decl = current_class_ref;
if (constructor_name (BINFO_TYPE (basebinfo)) == name)
{
if (dtor)
name = dtor_identifier;
else
name = ctor_identifier;
}
else
if (dtor)
my_friendly_abort (999);
fnfields = lookup_fnfields (basebinfo, name, 1); fnfields = lookup_fnfields (basebinfo, name, 1);
fields = lookup_field (basebinfo, name, 0, 0); fields = lookup_field (basebinfo, name, 0, 0);
......
...@@ -1847,6 +1847,11 @@ hack_identifier (value, name) ...@@ -1847,6 +1847,11 @@ hack_identifier (value, name)
else if (TREE_CODE (value) == NAMESPACE_DECL) else if (TREE_CODE (value) == NAMESPACE_DECL)
/* A namespace is not really expected here; this is likely illegal code. */ /* A namespace is not really expected here; this is likely illegal code. */
return value; return value;
else if (DECL_CLASS_TEMPLATE_P (value))
{
cp_error ("use of class template `%T' as expression", value);
value = error_mark_node;
}
else else
mark_used (value); mark_used (value);
......
...@@ -4774,7 +4774,11 @@ unary_complex_lvalue (code, arg) ...@@ -4774,7 +4774,11 @@ unary_complex_lvalue (code, arg)
/* Check all this code for right semantics. */ /* Check all this code for right semantics. */
if (TREE_CODE (t) == FUNCTION_DECL) if (TREE_CODE (t) == FUNCTION_DECL)
{
if (DECL_DESTRUCTOR_P (t))
cp_error ("taking address of destructor");
return build_unary_op (ADDR_EXPR, t, 0); return build_unary_op (ADDR_EXPR, t, 0);
}
if (TREE_CODE (t) == VAR_DECL) if (TREE_CODE (t) == VAR_DECL)
return build_unary_op (ADDR_EXPR, t, 0); return build_unary_op (ADDR_EXPR, t, 0);
else else
...@@ -5422,8 +5426,8 @@ build_static_cast (type, expr) ...@@ -5422,8 +5426,8 @@ build_static_cast (type, expr)
>= TYPE_READONLY (TREE_TYPE (TREE_TYPE (intype)))) >= TYPE_READONLY (TREE_TYPE (TREE_TYPE (intype))))
&& (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (type))) && (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (type)))
>= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (intype)))) >= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (intype))))
&& (binfo = get_binfo (TYPE_OFFSET_BASETYPE (intype), && (binfo = get_binfo (TYPE_OFFSET_BASETYPE (TREE_TYPE (type)),
TYPE_OFFSET_BASETYPE (type), 0)) TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)), 0))
&& ! TREE_VIA_VIRTUAL (binfo)) && ! TREE_VIA_VIRTUAL (binfo))
ok = 1; ok = 1;
} }
...@@ -7206,17 +7210,20 @@ c_expand_return (retval) ...@@ -7206,17 +7210,20 @@ c_expand_return (retval)
return; return;
} }
if (retval == NULL_TREE) if (dtor_label)
{ {
/* A non-named return value does not count. */ if (retval)
error ("returning a value from a destructor");
/* Can't just return from a destructor. */ /* Can't just return from a destructor. */
if (dtor_label)
{
expand_goto (dtor_label); expand_goto (dtor_label);
return; return;
} }
if (retval == NULL_TREE)
{
/* A non-named return value does not count. */
if (DECL_CONSTRUCTOR_P (current_function_decl)) if (DECL_CONSTRUCTOR_P (current_function_decl))
retval = current_class_ptr; retval = current_class_ptr;
else if (DECL_NAME (result) != NULL_TREE else if (DECL_NAME (result) != NULL_TREE
...@@ -7242,13 +7249,12 @@ c_expand_return (retval) ...@@ -7242,13 +7249,12 @@ c_expand_return (retval)
return; return;
} }
} }
else if (DECL_CONSTRUCTOR_P (current_function_decl) else if (DECL_CONSTRUCTOR_P (current_function_decl))
&& retval != current_class_ptr)
{ {
if (flag_this_is_variable) if (flag_this_is_variable)
error ("return from a constructor: use `this = ...' instead"); error ("return from a constructor: use `this = ...' instead");
else else
error ("return from a constructor"); error ("returning a value from a constructor");
retval = current_class_ptr; retval = current_class_ptr;
} }
......
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