diff options
author | Mark Mitchell <mark@markmitchell.com> | 1998-10-16 12:08:01 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1998-10-16 12:08:01 +0000 |
commit | 6b4b3deb4e4f5f7c8a5aab44b6907d006d78ac96 (patch) | |
tree | f1a18018ffc89c6255fe56cb63476779d58a8272 /gcc | |
parent | 4c37d704290d58c6788acee45877199d6e7b0bb5 (diff) | |
download | gcc-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/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/class.c | 57 | ||||
-rw-r--r-- | gcc/cp/decl.c | 58 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 30 | ||||
-rw-r--r-- | gcc/cp/method.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C | 56 |
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 +}; + |