diff options
author | Mark Mitchell <mark@codesourcery.com> | 1999-10-19 17:40:48 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-10-19 17:40:48 +0000 |
commit | 858a0ff1099497775acf5446b54e2eeeb19caae3 (patch) | |
tree | 4e9cd9c8532081cb216ff537118ff1cde0e91fa9 | |
parent | 9ce71c6fbd07e2d71d9e921e40b53d944f1f64d4 (diff) | |
download | gcc-858a0ff1099497775acf5446b54e2eeeb19caae3.zip gcc-858a0ff1099497775acf5446b54e2eeeb19caae3.tar.gz gcc-858a0ff1099497775acf5446b54e2eeeb19caae3.tar.bz2 |
method.c (PARM_CAN_BE_ARRAY_TYPE): Remove.
* method.c (PARM_CAN_BE_ARRAY_TYPE): Remove.
(mangling_flags): New type.
(build_overload_int): Change prototype.
(build_overload_value): Likewise.
(numeric_output_need_bar): Improve comment.
(mangle_expression): New function, broken out from ...
(build_overload_int): Here.
(build_overload_value): Adjust for use of mangling flags. Don't
warn about real-valued template parameters here. Do handle
complex expressions involving real-valued template parameters.
(build_template_parm_names): Encase non-type template parameters
in underscores, if necessary.
(process_overload_item): Remove conditional on
PARM_CAN_BE_ARRAY_TYPE.
From-SVN: r30090
-rw-r--r-- | gcc/cp/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/cp/NEWS | 7 | ||||
-rw-r--r-- | gcc/cp/method.c | 266 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.ext/realpt1.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/mangle1.C | 10 |
5 files changed, 214 insertions, 105 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 996d713..5a1d0e3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +1999-10-19 Mark Mitchell <mark@codesourcery.com> + + * method.c (PARM_CAN_BE_ARRAY_TYPE): Remove. + (mangling_flags): New type. + (build_overload_int): Change prototype. + (build_overload_value): Likewise. + (numeric_output_need_bar): Improve comment. + (mangle_expression): New function, broken out from ... + (build_overload_int): Here. + (build_overload_value): Adjust for use of mangling flags. Don't + warn about real-valued template parameters here. Do handle + complex expressions involving real-valued template parameters. + (build_template_parm_names): Encase non-type template parameters + in underscores, if necessary. + (process_overload_item): Remove conditional on + PARM_CAN_BE_ARRAY_TYPE. + 1999-10-17 Mark Mitchell <mark@codesourcery.com> * dump.c (dequeue_and_dump): Handle CLEANUP_POINT_EXPR. diff --git a/gcc/cp/NEWS b/gcc/cp/NEWS index a172f6d..fbe2cbb 100644 --- a/gcc/cp/NEWS +++ b/gcc/cp/NEWS @@ -1,5 +1,12 @@ *** Changes in GCC 3.0: +* In some obscure cases, functions with the same type could have the + same mangled name. This bug caused compiler crashes, link-time clashes, + and debugger crahses. Fixing this bug required breaking ABI + compatibility for the functions involved. The functions in questions + are those whose types involve non-type template arguments whose + mangled representations require more than one digit. + * Support for assignment to `this' has been removed. This idiom was used in the very early days of C++, before users were allowed to overload `operator new'; it is no longer allowed by the C++ diff --git a/gcc/cp/method.c b/gcc/cp/method.c index b5faca2..b188281 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -25,10 +25,6 @@ Boston, MA 02111-1307, USA. */ #define __inline #endif -#ifndef PARM_CAN_BE_ARRAY_TYPE -#define PARM_CAN_BE_ARRAY_TYPE 1 -#endif - /* Handle method declarations. */ #include "config.h" #include "system.h" @@ -44,6 +40,24 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #include "tm_p.h" +/* Various flags to control the mangling process. */ + +enum mangling_flags +{ + /* No flags. */ + mf_none = 0, + /* The thing we are presently mangling is part of a template type, + rather than a fully instantiated type. Therefore, we may see + complex expressions where we would normally expect to see a + simple integer constant. */ + mf_maybe_uninstantiated = 1, + /* When mangling a numeric value, use the form `_XX_' (instead of + just `XX') if the value has more than one digit. */ + mf_use_underscores_around_value = 2, +}; + +typedef enum mangling_flags mangling_flags; + /* TREE_LIST of the current inline functions that need to be processed. */ struct pending_inline *pending_inlines; @@ -61,10 +75,11 @@ static int old_backref_index PROTO((tree)); static int flush_repeats PROTO((int, tree)); static void build_overload_identifier PROTO((tree)); static void build_overload_nested_name PROTO((tree)); -static void build_overload_int PROTO((tree, int)); +static void mangle_expression PROTO((tree)); +static void build_overload_int PROTO((tree, mangling_flags)); static void build_overload_identifier PROTO((tree)); static void build_qualified_name PROTO((tree)); -static void build_overload_value PROTO((tree, tree, int)); +static void build_overload_value PROTO((tree, tree, mangling_flags)); static void issue_nrepeats PROTO((int, tree)); static char *build_mangled_name PROTO((tree,int,int)); static void process_modifiers PROTO((tree)); @@ -197,8 +212,8 @@ do_inline_function_hair (type, friend_list) /* Nonzero if we should not try folding parameter types. */ static int nofold; -/* This appears to be set to true if an underscore is required to be - comcatenated before another number can be outputed. */ +/* Nonzero if an underscore is required before adding a digit to the + mangled name currently being built. */ static int numeric_output_need_bar; static __inline void @@ -546,104 +561,141 @@ build_overload_scope_ref (value) build_overload_identifier (TREE_OPERAND (value, 1)); } -/* Encoding for an INTEGER_CST value. */ +/* VALUE is a complex expression. Produce an appropriate mangling. + (We are forced to mangle complex expressions when dealing with + templates, and an expression involving template parameters appears + in the type of a function parameter.) */ static void -build_overload_int (value, in_template) +mangle_expression (value) tree value; - int in_template; { - if (in_template && TREE_CODE (value) != INTEGER_CST) + if (TREE_CODE (value) == SCOPE_REF) { - if (TREE_CODE (value) == SCOPE_REF) - { - build_overload_scope_ref (value); - return; - } + build_overload_scope_ref (value); + return; + } - OB_PUTC ('E'); - numeric_output_need_bar = 0; + OB_PUTC ('E'); + numeric_output_need_bar = 0; - if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value)))) + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value)))) + { + int i; + int operands = tree_code_length[(int) TREE_CODE (value)]; + tree id; + const char *name; + + id = ansi_opname [(int) TREE_CODE (value)]; + my_friendly_assert (id != NULL_TREE, 0); + name = IDENTIFIER_POINTER (id); + if (name[0] != '_' || name[1] != '_') + /* On some erroneous inputs, we can get here with VALUE a + LOOKUP_EXPR. In that case, the NAME will be the + identifier for "<invalid operator>". We must survive + this routine in order to issue a sensible error + message, so we fall through to the case below. */ + goto bad_value; + + for (i = 0; i < operands; ++i) { - int i; - int operands = tree_code_length[(int) TREE_CODE (value)]; - tree id; - const char *name; - - id = ansi_opname [(int) TREE_CODE (value)]; - my_friendly_assert (id != NULL_TREE, 0); - name = IDENTIFIER_POINTER (id); - if (name[0] != '_' || name[1] != '_') - /* On some erroneous inputs, we can get here with VALUE a - LOOKUP_EXPR. In that case, the NAME will be the - identifier for "<invalid operator>". We must survive - this routine in order to issue a sensible error - message, so we fall through to the case below. */ - goto bad_value; - - for (i = 0; i < operands; ++i) - { - tree operand; - enum tree_code tc; + tree operand; + enum tree_code tc; - /* We just outputted either the `E' or the name of the - operator. */ - numeric_output_need_bar = 0; + /* We just outputted either the `E' or the name of the + operator. */ + numeric_output_need_bar = 0; - if (i != 0) - /* Skip the leading underscores. */ - OB_PUTCP (name + 2); + if (i != 0) + /* Skip the leading underscores. */ + OB_PUTCP (name + 2); - operand = TREE_OPERAND (value, i); - tc = TREE_CODE (operand); + operand = TREE_OPERAND (value, i); + tc = TREE_CODE (operand); - if (TREE_CODE_CLASS (tc) == 't') - /* We can get here with sizeof, e.g.: + if (TREE_CODE_CLASS (tc) == 't') + /* We can get here with sizeof, e.g.: - template <class T> void f(A<sizeof(T)>); */ - build_mangled_name_for_type (operand); - else if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc))) - build_overload_int (operand, in_template); - else - build_overload_value (TREE_TYPE (operand), - operand, - in_template); - } + template <class T> void f(A<sizeof(T)>); */ + build_mangled_name_for_type (operand); + else + build_overload_value (TREE_TYPE (operand), + operand, + mf_maybe_uninstantiated); } - else - { - /* We don't ever want this output, but it's - inconvenient not to be able to build the string. - This should cause assembler errors we'll notice. */ + } + else + { + /* We don't ever want this output, but it's + inconvenient not to be able to build the string. + This should cause assembler errors we'll notice. */ - static int n; - bad_value: - sprintf (digit_buffer, " *%d", n++); - OB_PUTCP (digit_buffer); - } + static int n; + bad_value: + sprintf (digit_buffer, " *%d", n++); + OB_PUTCP (digit_buffer); + } - OB_PUTC ('W'); - numeric_output_need_bar = 0; + OB_PUTC ('W'); + numeric_output_need_bar = 0; +} + +/* Encoding for an INTEGER_CST value. */ + +static void +build_overload_int (value, flags) + tree value; + mangling_flags flags; +{ + int multiple_words_p = 0; + int multiple_digits_p = 0; + + if ((flags & mf_maybe_uninstantiated) && TREE_CODE (value) != INTEGER_CST) + { + mangle_expression (value); return; } + /* Unless we were looking at an uninstantiated template, integers + should always be represented by constants. */ my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); - if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT) + + /* If the high-order word is not merely a sign-extension of the + low-order word, we must use a special output routine that can + deal with this. */ + if (TREE_INT_CST_HIGH (value) + != (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1))) { - if (TREE_INT_CST_HIGH (value) - != (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1))) - { - /* need to print a DImode value in decimal */ - dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value)); - numeric_output_need_bar = 1; - return; - } - /* else fall through to print in smaller mode */ + multiple_words_p = 1; + /* And there is certainly going to be more than one digit. */ + multiple_digits_p = 1; + } + else + multiple_digits_p = (TREE_INT_CST_LOW (value) > 9 + || TREE_INT_CST_LOW (value) < -9); + + /* If necessary, add a leading underscore. */ + if (multiple_digits_p && (flags & mf_use_underscores_around_value)) + OB_PUTC ('_'); + + /* Output the number itself. */ + if (multiple_words_p) + dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value)); + else + icat (TREE_INT_CST_LOW (value)); + + if (flags & mf_use_underscores_around_value) + { + if (multiple_digits_p) + OB_PUTC ('_'); + /* Whether or not there were multiple digits, we don't need an + underscore. We've either terminated the number with an + underscore, or else it only had one digit. */ + numeric_output_need_bar = 0; } - /* Wordsize or smaller */ - icat (TREE_INT_CST_LOW (value)); - numeric_output_need_bar = 1; + else + /* We just output a numeric value. */ + numeric_output_need_bar = 1; } @@ -701,9 +753,9 @@ build_mangled_C9x_name (bits) #endif static void -build_overload_value (type, value, in_template) +build_overload_value (type, value, flags) tree type, value; - int in_template; + mangling_flags flags; { my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0); @@ -738,24 +790,31 @@ build_overload_value (type, value, in_template) build_overload_identifier (DECL_NAME (value)); return; } + else if (INTEGRAL_TYPE_P (type)) + { + build_overload_int (value, flags); + return; + } + + /* The only case where we use the extra underscores here is when + forming the mangling for an integral non-type template argument. + If that didn't happen, stop now. */ + flags &= ~mf_use_underscores_around_value; switch (TREE_CODE (type)) { - case INTEGER_TYPE: - case ENUMERAL_TYPE: - case BOOLEAN_TYPE: - { - build_overload_int (value, in_template); - return; - } case REAL_TYPE: { REAL_VALUE_TYPE val; char *bufp = digit_buffer; - pedwarn ("ANSI C++ forbids floating-point template arguments"); + /* We must handle non-constants in templates. */ + if (TREE_CODE (value) != REAL_CST) + { + mangle_expression (value); + break; + } - my_friendly_assert (TREE_CODE (value) == REAL_CST, 244); val = TREE_REAL_CST (value); if (REAL_VALUE_ISNAN (val)) { @@ -817,7 +876,7 @@ build_overload_value (type, value, in_template) case POINTER_TYPE: if (TREE_CODE (value) == INTEGER_CST) { - build_overload_int (value, in_template); + build_overload_int (value, flags); return; } else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) @@ -877,9 +936,9 @@ build_overload_value (type, value, in_template) my_friendly_assert (TREE_CODE (value) == PTRMEM_CST, 0); expand_ptrmemfunc_cst (value, &delta, &idx, &pfn, &delta2); - build_overload_int (delta, in_template); + build_overload_int (delta, flags); OB_PUTC ('_'); - build_overload_int (idx, in_template); + build_overload_int (idx, flags); OB_PUTC ('_'); if (pfn) { @@ -890,7 +949,7 @@ build_overload_value (type, value, in_template) else { OB_PUTC ('i'); - build_overload_int (delta2, in_template); + build_overload_int (delta2, flags); } } break; @@ -983,7 +1042,9 @@ build_template_parm_names (parmlist, arglist) /* It's a PARM_DECL. */ build_mangled_name_for_type (TREE_TYPE (parm)); build_overload_value (TREE_TYPE (parm), arg, - uses_template_parms (arglist)); + ((mf_maybe_uninstantiated + * uses_template_parms (arglist)) + | mf_use_underscores_around_value)); } } } @@ -1317,7 +1378,6 @@ process_overload_item (parmtype, extra_Gcode) goto more; case ARRAY_TYPE: -#if PARM_CAN_BE_ARRAY_TYPE { OB_PUTC ('A'); if (TYPE_DOMAIN (parmtype) == NULL_TREE) @@ -1337,10 +1397,6 @@ process_overload_item (parmtype, extra_Gcode) OB_PUTC ('_'); goto more; } -#else - OB_PUTC ('P'); - goto more; -#endif case POINTER_TYPE: OB_PUTC ('P'); diff --git a/gcc/testsuite/g++.old-deja/g++.ext/realpt1.C b/gcc/testsuite/g++.old-deja/g++.ext/realpt1.C new file mode 100644 index 0000000..7e8ea91 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.ext/realpt1.C @@ -0,0 +1,19 @@ +// Build don't link: +// Special g++ Options: +// Origin: Mark Mitchell <mark@codesourcery.com> + +template <double d> +struct S; + +template <double d, double e> +void f (S<d>*, S<e>*, S<d + e>*); + +void g () +{ + S<2.0>* s1; + S<3.7>* s2; + S<5.7>* s3; + + f (s1, s2, s3); +} + diff --git a/gcc/testsuite/g++.old-deja/g++.pt/mangle1.C b/gcc/testsuite/g++.old-deja/g++.pt/mangle1.C new file mode 100644 index 0000000..fdebc0c --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/mangle1.C @@ -0,0 +1,10 @@ +// Build don't link: +// Origin: Mark Mitchell <mark@codesourcery.com> + +typedef enum {} i; + +template <int II> +class Bar {}; + +void f (Bar<21>, int) {} +void f (Bar<2>, i) {} |