+1998-09-28 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Tighten checks for invalid
+ destructors. Improve error-messages and error-recovery.
+ * decl2.c (check_classfn): Don't assume that mangled destructor
+ names contain type information.
+
1998-09-25 Jason Merrill <jason@yorick.cygnus.com>
* search.c (get_base_distance): Remove assert.
error ("destructor cannot be static member function");
if (quals)
{
- error ("destructors cannot be declared `const' or `volatile'");
- return void_type_node;
+ cp_error ("destructors may not be `%s'",
+ IDENTIFIER_POINTER (TREE_VALUE (quals)));
+ quals = NULL_TREE;
}
if (decl_context == FIELD)
{
}
if (quals)
{
- error ("constructors cannot be declared `const' or `volatile'");
- return void_type_node;
+ cp_error ("constructors may not be `%s'",
+ IDENTIFIER_POINTER (TREE_VALUE (quals)));
+ quals = NULL_TREE;
}
{
RID_BIT_TYPE tmp_bits;
arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0);
- if (declarator)
+ if (declarator && flags == DTOR_FLAG)
{
- /* Get past destructors, etc.
- We know we have one because FLAGS will be non-zero.
-
- Complain about improper parameter lists here. */
+ /* A destructor declared in the body of a class will
+ be represented as a BIT_NOT_EXPR. But, we just
+ want the underlying IDENTIFIER. */
if (TREE_CODE (declarator) == BIT_NOT_EXPR)
+ declarator = TREE_OPERAND (declarator, 0);
+
+ if (strict_prototype == 0 && arg_types == NULL_TREE)
+ arg_types = void_list_node;
+ else if (arg_types == NULL_TREE
+ || arg_types != void_list_node)
{
- declarator = TREE_OPERAND (declarator, 0);
-
- if (strict_prototype == 0 && arg_types == NULL_TREE)
- arg_types = void_list_node;
- else if (arg_types == NULL_TREE
- || arg_types != void_list_node)
- {
- error ("destructors cannot be specified with parameters");
- arg_types = void_list_node;
- }
+ cp_error ("destructors may not have parameters");
+ arg_types = void_list_node;
+ last_function_parms = NULL_TREE;
}
}
fndecl = OVL_CURRENT (fndecls);
/* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL is
not mangled, so the check below does not work
- correctly in that case. */
+ correctly in that case. Since mangled destructor names
+ do not include the type of the arguments, we
+ can't use this short-cut for them, either. */
if (TREE_CODE (function) != TEMPLATE_DECL
&& TREE_CODE (fndecl) != TEMPLATE_DECL
+ && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))
&& (DECL_ASSEMBLER_NAME (function)
== DECL_ASSEMBLER_NAME (fndecl)))
return fndecl;
--- /dev/null
+// Build don't link:
+
+struct S1
+{
+ ~S1(int); // ERROR - destructors may not have parameters
+};
+
+
+template <class T>
+struct S2
+{
+ ~S2(int); // ERROR - destructors may not have parameters
+};
+
+
+struct S3
+{
+ ~S3(double) {} // ERROR - destructors may not have parameters
+};
+
+
+template <class T>
+struct S4
+{
+ ~S4(double) {} // ERROR - destructors may not have parameters
+};
+
+
+struct S5
+{
+ ~S5();
+};
+
+S5::~S5(float)
+{ // ERROR - destructors may not have parameters
+}
+
+
+template <class T>
+struct S6
+{
+ ~S6();
+};
+
+template <class T>
+S6<T>::~S6(float)
+{ // ERROR - destructors may not have parameters
+}
+
+
+
--- /dev/null
+// Build don't link:
+
+struct S1 {
+ ~S1(); // ERROR - candidate
+};
+
+S1::~S1() const
+{ // ERROR - prototype does not match
+}
+
+
+struct S2 {
+ ~S2() volatile; // ERROR - destructors may not be volatile
+};
+
+
+template <class T>
+struct S3 {
+ ~S3(); // ERROR - candidate
+};
+
+template <class T>
+S3<T>::~S3() volatile
+{ // ERROR - prototype does not match
+}
+
+
+template <class T>
+struct S4 {
+ ~S4() const; // ERROR - destructors may not be const
+};