Commit 6b4b3deb by Mark Mitchell Committed by Mark Mitchell

class.c (add_method): Fix documentation to reflect previous changes.

	* class.c (add_method): Fix documentation to reflect previous
	changes.  Check for duplicate method declarations here.
	* decl.c (decls_match): Handle FUNCTION_DECL vs TEMPLATE_DECL
	correctly; such things never match.
	(grokfndecl): Don't look for duplicate methods here.
	* decl2.c (check_classfn): Don't assume names are mangled.
	Don't add bogus member function declarations to a class before the
	class type is complete.
	(grokfield): Reformat error message.
	* method.c (set_mangled_name_for_decl): Don't mangle names while
	procesing_template_decl.

From-SVN: r23132
parent 4c37d704
1998-10-16 Mark Mitchell <mark@markmitchell.com>
* class.c (add_method): Fix documentation to reflect previous
changes. Check for duplicate method declarations here.
* decl.c (decls_match): Handle FUNCTION_DECL vs TEMPLATE_DECL
correctly; such things never match.
(grokfndecl): Don't look for duplicate methods here.
* decl2.c (check_classfn): Don't assume names are mangled.
Don't add bogus member function declarations to a class before the
class type is complete.
(grokfield): Reformat error message.
* method.c (set_mangled_name_for_decl): Don't mangle names while
procesing_template_decl.
1998-10-16 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (build_indirect_ref): Complain about a pointer to data
......
......@@ -1109,12 +1109,10 @@ free_method_vec (vec)
free_method_vecs = vec;
}
/* Add method METHOD to class TYPE. This is used when a method
has been defined which did not initially appear in the class definition,
and helps cut down on spurious error messages.
/* Add method METHOD to class TYPE.
FIELDS is the entry in the METHOD_VEC vector entry of the class type where
the method should be added. */
If non-NULL, FIELDS is the entry in the METHOD_VEC vector entry of
the class type where the method should be added. */
void
add_method (type, fields, method)
......@@ -1184,6 +1182,52 @@ add_method (type, fields, method)
len = 2 * len;
method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
}
else if (template_class_depth (type))
/* TYPE is a template class. Don't issue any errors now;
wait until instantiation time to complain. */
;
else
{
tree fns;
/* Check to see if we've already got this method. */
for (fns = TREE_VEC_ELT (method_vec, i);
fns;
fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) != TREE_CODE (method))
continue;
if (TREE_CODE (method) != TEMPLATE_DECL)
{
/* Since this is an ordinary function in a
non-template class, it's mangled name can be
used as a unique identifier. This technique
is only an optimization; we would get the
same results if we just used decls_match
here. */
if (DECL_ASSEMBLER_NAME (fn)
!= DECL_ASSEMBLER_NAME (method))
continue;
}
else if (!decls_match (fn, method))
continue;
/* There has already been a declaration of this
method or member template. */
cp_error_at ("`%D' has already been declared in `%T'",
method, type);
/* We don't call duplicate_decls here to merege the
declarations because that will confuse things if
the methods have inline definitions In
particular, we will crash while processing the
definitions. */
return;
}
}
if (IDENTIFIER_TYPENAME_P (DECL_NAME (method)))
{
......@@ -1226,6 +1270,9 @@ add_method (type, fields, method)
}
}
/* Create RTL for the METHOD. */
make_decl_rtl (method, NULL_PTR, 1);
/* Actually insert the new method. */
TREE_VEC_ELT (method_vec, i)
= build_overload (method, TREE_VEC_ELT (method_vec, i));
......
......@@ -2511,8 +2511,12 @@ decls_match (newdecl, olddecl)
{
int types_match;
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL)
if (TREE_CODE (newdecl) != TREE_CODE (olddecl))
/* If the two DECLs are not even the same kind of thing, we're not
interested in their types. */
return 0;
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
tree f2 = TREE_TYPE (olddecl);
......@@ -2568,8 +2572,7 @@ decls_match (newdecl, olddecl)
else
types_match = 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (olddecl) == TEMPLATE_DECL)
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
......@@ -8184,22 +8187,6 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
}
if (! grok_ctor_properties (ctype, decl))
return error_mark_node;
if (check == 0 && ! current_function_decl)
{
/* Assembler names live in the global namespace. */
tmp = IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl));
if (tmp == NULL_TREE)
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
else if (TREE_CODE (tmp) != TREE_CODE (decl))
cp_error ("inconsistent declarations for `%D'", decl);
else
{
duplicate_decls (decl, tmp);
decl = tmp;
}
make_decl_rtl (decl, NULL_PTR, 1);
}
}
else
{
......@@ -8248,37 +8235,6 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (ctype == NULL_TREE || check)
return decl;
/* Now install the declaration of this function so that others may
find it (esp. its DECL_FRIENDLIST). Don't do this for local class
methods, though. */
if (! current_function_decl)
{
if (!DECL_TEMPLATE_SPECIALIZATION (decl))
{
/* We don't do this for specializations since the
equivalent checks will be done later. Also, at this
point the DECL_ASSEMBLER_NAME is not yet fully
accurate. */
/* FIXME: this should only need to look at
IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
if (tmp == NULL_TREE)
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
else if (TREE_CODE (tmp) != TREE_CODE (decl))
cp_error ("inconsistent declarations for `%D'", decl);
else
{
duplicate_decls (decl, tmp);
decl = tmp;
}
}
if (attrlist)
cplus_decl_attributes (decl, TREE_PURPOSE (attrlist),
TREE_VALUE (attrlist));
make_decl_rtl (decl, NULL_PTR, 1);
}
if (virtualp)
{
DECL_VIRTUAL_P (decl) = 1;
......
......@@ -1383,14 +1383,19 @@ check_classfn (ctype, function)
fndecls = OVL_NEXT (fndecls))
{
fndecl = OVL_CURRENT (fndecls);
/* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL is
/* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL, or
for a for member function of a template class, is
not mangled, so the check below does not work
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))
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.
(It's not legal to declare arguments for a
destructor, but some people try.) */
if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))
&& (DECL_ASSEMBLER_NAME (function)
!= DECL_NAME (function))
&& (DECL_ASSEMBLER_NAME (fndecl)
!= DECL_NAME (fndecl))
&& (DECL_ASSEMBLER_NAME (function)
== DECL_ASSEMBLER_NAME (fndecl)))
return fndecl;
......@@ -1467,8 +1472,11 @@ check_classfn (ctype, function)
}
/* If we did not find the method in the class, add it to avoid
spurious errors. */
add_method (ctype, methods, function);
spurious errors (unless the CTYPE is not yet defined, in which
case we'll only confuse ourselves when the function is declared
properly within the class. */
if (TYPE_SIZE (ctype))
add_method (ctype, methods, function);
return NULL_TREE;
}
......@@ -1573,8 +1581,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
if (DECL_IN_AGGR_P (value))
{
cp_error ("`%D' is already defined in the class %T", value,
DECL_CONTEXT (value));
cp_error ("`%D' is already defined in `%T'", value,
DECL_CONTEXT (value));
return void_type_node;
}
......
......@@ -1662,7 +1662,13 @@ void
set_mangled_name_for_decl (decl)
tree decl;
{
tree parm_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree parm_types;
if (processing_template_decl)
/* There's no need to mangle the name of a template function. */
return;
parm_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
if (DECL_STATIC_FUNCTION_P (decl))
parm_types =
......
......@@ -31,16 +31,16 @@ class C
class D
{
public:
int foo2() {return b;} // WARNING -
int foo2() {return b;} // WARNING -
int foo2() {return b;}
int foo2() {return b;} // ERROR -
int b;
};
class E
{
public:
int foo2(); // WARNING -
int foo2(); // WARNING -
int foo2();
int foo2(); // ERROR -
int b;
};
......
// Build don't link:
struct A
{
void f() {}
template <class U>
void f() {}
};
template <class T>
struct B
{
void f() {}
template <class U>
void f() {}
};
template struct B<int>;
struct C
{
template <class U>
void f() {}
template <class U>
void f() {} // ERROR - redeclaration
};
template <class T, class U>
struct D
{
void f(T);
void f(U);
};
template struct D<int, double>;
template <class T, class U>
struct D2
{
void f(T);
void f(U); // ERROR - redeclaration
};
template struct D2<int, int>;
struct E
{
void f();
void f(); // ERROR - redeclaration
};
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