+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>
* class.c (alter_access): Accept a BINFO explaining how to get
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)'.
This is how virtual function calls are avoided. */
binfo = NULL_TREE;
/* Check the destructor call syntax. */
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- 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'",
- basetype, TREE_OPERAND (name, 0));
- return error_mark_node;
- }
- }
+ if (TREE_CODE (name) == BIT_NOT_EXPR && ! check_dtor_name (basetype, name))
+ cp_error ("qualified type `%T' does not match destructor name `~%T'",
+ basetype, TREE_OPERAND (name, 0));
/* 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
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- tree tmp;
-
- tmp = name = TREE_OPERAND (name, 0);
-
if (parms)
error ("destructors take no parameters");
basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
- 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 ("destructor name `~%T' does not match type `%T' of expression",
- name, basetype);
- return cp_convert (void_type_node, instance);
- }
+ if (! check_dtor_name (basetype, name))
+ cp_error
+ ("destructor name `~%T' does not match type `%T' of expression",
+ TREE_OPERAND (name, 0), basetype);
if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
return cp_convert (void_type_node, instance);
expand_end_bindings (decls, decls != NULL_TREE, 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
&& return_label != NULL_RTX)
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_just_assigned_this = 0;
{
tree decl, fnfields, fields, t = error_mark_node;
tree basebinfo = NULL_TREE;
- int dtor = 0;
tree orig_name = name;
/* class templates can come in as TEMPLATE_DECLs here. */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- dtor = 1;
- name = TREE_OPERAND (name, 0);
+ if (! check_dtor_name (type, name))
+ cp_error ("qualified type `%T' does not match destructor name `~%T'",
+ type, TREE_OPERAND (name, 0));
+ name = dtor_identifier;
}
-
- if (name == constructor_name_full (type))
- name = constructor_name (type);
+#if 0
+ /* I think this is wrong, but the draft is unclear. --jason 6/15/98 */
+ else if (name == constructor_name_full (type)
+ || name == constructor_name (type))
+ name = ctor_identifier;
+#endif
if (TYPE_SIZE (complete_type (type)) == 0)
{
else
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);
fields = lookup_field (basebinfo, name, 0, 0);
else if (TREE_CODE (value) == NAMESPACE_DECL)
/* A namespace is not really expected here; this is likely illegal code. */
return value;
+ else if (DECL_CLASS_TEMPLATE_P (value))
+ {
+ cp_error ("use of class template `%T' as expression", value);
+ value = error_mark_node;
+ }
else
mark_used (value);
/* Check all this code for right semantics. */
if (TREE_CODE (t) == FUNCTION_DECL)
- return build_unary_op (ADDR_EXPR, t, 0);
+ {
+ if (DECL_DESTRUCTOR_P (t))
+ cp_error ("taking address of destructor");
+ return build_unary_op (ADDR_EXPR, t, 0);
+ }
if (TREE_CODE (t) == VAR_DECL)
return build_unary_op (ADDR_EXPR, t, 0);
else
>= TYPE_READONLY (TREE_TYPE (TREE_TYPE (intype))))
&& (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (type)))
>= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (intype))))
- && (binfo = get_binfo (TYPE_OFFSET_BASETYPE (intype),
- TYPE_OFFSET_BASETYPE (type), 0))
+ && (binfo = get_binfo (TYPE_OFFSET_BASETYPE (TREE_TYPE (type)),
+ TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)), 0))
&& ! TREE_VIA_VIRTUAL (binfo))
ok = 1;
}
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. */
- if (dtor_label)
- {
- expand_goto (dtor_label);
- return;
- }
+ expand_goto (dtor_label);
+ return;
+ }
+
+ if (retval == NULL_TREE)
+ {
+ /* A non-named return value does not count. */
if (DECL_CONSTRUCTOR_P (current_function_decl))
retval = current_class_ptr;
return;
}
}
- else if (DECL_CONSTRUCTOR_P (current_function_decl)
- && retval != current_class_ptr)
+ else if (DECL_CONSTRUCTOR_P (current_function_decl))
{
if (flag_this_is_variable)
error ("return from a constructor: use `this = ...' instead");
else
- error ("return from a constructor");
+ error ("returning a value from a constructor");
retval = current_class_ptr;
}