aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-10-16 12:08:01 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-10-16 12:08:01 +0000
commit6b4b3deb4e4f5f7c8a5aab44b6907d006d78ac96 (patch)
treef1a18018ffc89c6255fe56cb63476779d58a8272 /gcc
parent4c37d704290d58c6788acee45877199d6e7b0bb5 (diff)
downloadgcc-6b4b3deb4e4f5f7c8a5aab44b6907d006d78ac96.zip
gcc-6b4b3deb4e4f5f7c8a5aab44b6907d006d78ac96.tar.gz
gcc-6b4b3deb4e4f5f7c8a5aab44b6907d006d78ac96.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/class.c57
-rw-r--r--gcc/cp/decl.c58
-rw-r--r--gcc/cp/decl2.c30
-rw-r--r--gcc/cp/method.c8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C56
7 files changed, 159 insertions, 72 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1b93d02..50694ee 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index d503296..2bc8f37 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 75a37a6..f296fa2 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 92e01fe..f20d6f2 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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;
}
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 82a886c..400aead 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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 =
diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C b/gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C
index a60a2d7..e63d43c 100644
--- a/gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C
+++ b/gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C
@@ -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;
};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C
new file mode 100644
index 0000000..945e7ff
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C
@@ -0,0 +1,56 @@
+// 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
+};
+