aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@yorick.cygnus.com>1998-06-16 02:51:01 +0000
committerJason Merrill <jason@gcc.gnu.org>1998-06-15 22:51:01 -0400
commit1c2c08a5531fb816f8da4599428d6a8223dd3d5a (patch)
treefa90bdc903bf55966857420c39e6ce0bdf3f83fc
parent8b45da67d0eaa8d7fec5913d9439d88865edfc55 (diff)
downloadgcc-1c2c08a5531fb816f8da4599428d6a8223dd3d5a.zip
gcc-1c2c08a5531fb816f8da4599428d6a8223dd3d5a.tar.gz
gcc-1c2c08a5531fb816f8da4599428d6a8223dd3d5a.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/call.c85
-rw-r--r--gcc/cp/decl.c6
-rw-r--r--gcc/cp/init.c28
-rw-r--r--gcc/cp/method.c5
-rw-r--r--gcc/cp/typeck.c32
6 files changed, 89 insertions, 82 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 897a1a1..ea7f271 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,18 @@
+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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 429b4cf..8999897 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -340,6 +340,35 @@ resolve_scope_to_name (outer_type, inner_stuff)
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. */
@@ -386,31 +415,9 @@ build_scoped_method_call (exp, basetype, name, parms)
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
@@ -645,36 +652,16 @@ build_method_call (instance, name, parms, basetype_path, flags)
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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e6c5fff..20dfdf7 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -12599,7 +12599,8 @@ finish_function (lineno, call_poplevel, nested)
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)
@@ -12666,7 +12667,8 @@ finish_function (lineno, call_poplevel, nested)
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;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index aa8fb0c..84015b0 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1521,7 +1521,6 @@ build_offset_ref (type, name)
{
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. */
@@ -1553,12 +1552,17 @@ build_offset_ref (type, name)
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)
{
@@ -1598,18 +1602,6 @@ build_offset_ref (type, name)
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);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index cc01371..1414870 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1847,6 +1847,11 @@ hack_identifier (value, name)
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);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index b8a46d1..b038a86 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4774,7 +4774,11 @@ unary_complex_lvalue (code, arg)
/* 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
@@ -5422,8 +5426,8 @@ build_static_cast (type, expr)
>= 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;
}
@@ -7206,16 +7210,19 @@ c_expand_return (retval)
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;
@@ -7242,13 +7249,12 @@ c_expand_return (retval)
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;
}