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
This commit is contained in:
parent
9ce71c6fbd
commit
858a0ff109
5 changed files with 224 additions and 115 deletions
|
@ -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.
|
||||
|
|
|
@ -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++
|
||||
|
|
286
gcc/cp/method.c
286
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;
|
||||
}
|
||||
|
||||
OB_PUTC ('E');
|
||||
numeric_output_need_bar = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
tree operand;
|
||||
enum tree_code tc;
|
||||
|
||||
/* 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);
|
||||
|
||||
operand = TREE_OPERAND (value, i);
|
||||
tc = TREE_CODE (operand);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
OB_PUTC ('W');
|
||||
numeric_output_need_bar = 0;
|
||||
build_overload_scope_ref (value);
|
||||
return;
|
||||
}
|
||||
|
||||
my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243);
|
||||
if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT)
|
||||
OB_PUTC ('E');
|
||||
numeric_output_need_bar = 0;
|
||||
|
||||
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value))))
|
||||
{
|
||||
if (TREE_INT_CST_HIGH (value)
|
||||
!= (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1)))
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
tree operand;
|
||||
enum tree_code tc;
|
||||
|
||||
/* 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);
|
||||
|
||||
operand = TREE_OPERAND (value, i);
|
||||
tc = TREE_CODE (operand);
|
||||
|
||||
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
|
||||
build_overload_value (TREE_TYPE (operand),
|
||||
operand,
|
||||
mf_maybe_uninstantiated);
|
||||
}
|
||||
/* else fall through to print in smaller mode */
|
||||
}
|
||||
/* Wordsize or smaller */
|
||||
icat (TREE_INT_CST_LOW (value));
|
||||
numeric_output_need_bar = 1;
|
||||
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);
|
||||
}
|
||||
|
||||
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 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)))
|
||||
{
|
||||
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;
|
||||
}
|
||||
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');
|
||||
|
|
19
gcc/testsuite/g++.old-deja/g++.ext/realpt1.C
Normal file
19
gcc/testsuite/g++.old-deja/g++.ext/realpt1.C
Normal file
|
@ -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);
|
||||
}
|
||||
|
10
gcc/testsuite/g++.old-deja/g++.pt/mangle1.C
Normal file
10
gcc/testsuite/g++.old-deja/g++.pt/mangle1.C
Normal file
|
@ -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) {}
|
Loading…
Add table
Reference in a new issue