Index: vendor/gcc/2.95-20000526/contrib/gcc/config/alpha/linux-elf.h =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/config/alpha/linux-elf.h (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/config/alpha/linux-elf.h (revision 60969) @@ -0,0 +1,48 @@ +/* Definitions of target machine for GNU compiler + for Alpha Linux-based GNU systems using ELF. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Richard Henderson. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux for ELF)"); + +#undef SUBTARGET_EXTRA_SPECS +#define SUBTARGET_EXTRA_SPECS \ +{ "elf_dynamic_linker", ELF_DYNAMIC_LINKER }, + +#undef SUB_CPP_PREDEFINES +#define SUB_CPP_PREDEFINES "-D__ELF__" + +#ifdef USE_GNULIBC_1 +#define ELF_DYNAMIC_LINKER "/lib/ld.so.1" +#else +#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2" +#endif + +#ifndef USE_GNULIBC_1 +#undef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 2 +#endif + +#ifndef USE_GNULIBC_1 +#undef LIB_SPEC +#define LIB_SPEC \ +"%{shared:-lc}%{!shared:%{pthread:-lpthread }%{profile:-lc_p}%{!profile:-lc}} " +#endif Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/config/alpha/linux-elf.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/config/i386/freebsd.h =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/config/i386/freebsd.h (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/config/i386/freebsd.h (revision 60969) @@ -0,0 +1,257 @@ +/* Definitions for Intel 386 running FreeBSD with ELF format + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Eric Youngdale. + Modified for stabs-in-ELF by H.J. Lu. + Adapted from GNU/Linux version by John Polstra. + Continued development by David O'Brien + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); + +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ +/* On FreeBSD, we do not. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using + libraries compiled with the native cc, so undef it. */ +#undef NO_DOLLAR_IN_LABEL + +/* Use more efficient ``thunks'' to implement C++ vtables. */ +#undef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 2 + +/* Override the default comment-starter of "/". */ +#undef ASM_COMMENT_START +#define ASM_COMMENT_START "#" + +#undef ASM_APP_ON +#define ASM_APP_ON "#APP\n" + +#undef ASM_APP_OFF +#define ASM_APP_OFF "#NO_APP\n" + +#undef SET_ASM_OP +#define SET_ASM_OP ".set" + +/* This is how to output an element of a case-vector that is relative. + This is only used for PIC code. See comments by the `casesi' insn in + i386.md for an explanation of the expression this outputs. */ +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ + fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) + +/* Indicate that jump tables go in the text section. This is + necessary when compiling PIC code. */ +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) + +/* Use stabs instead of DWARF debug format. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +/* Copy this from the svr4 specifications... */ +/* Define the register numbers to be used in Dwarf debugging information. + The SVR4 reference port C compiler uses the following register numbers + in its Dwarf output code: + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) + +/* Tell final.c that we don't need a label passed to mcount. */ + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ +{ \ + if (flag_pic) \ + fprintf (FILE, "\tcall *.mcount@GOT(%%ebx)\n"); \ + else \ + fprintf (FILE, "\tcall .mcount\n"); \ +} + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_UNSIGNED +#define WCHAR_UNSIGNED 0 + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Dunix -D__ELF__ -D__FreeBSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" + +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" + +/* This defines which switch letters take arguments. On FreeBSD, most of + the normal cases (defined in gcc.c) apply, and we also have -h* and + -z* options (for the linker) (comming from svr4). + We also have -R (alias --rpath), no -z, --soname (-h), --assert etc. */ + +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + (DEFAULT_SWITCH_TAKES_ARG (CHAR) \ + || (CHAR) == 'h' \ + || (CHAR) == 'z' \ + || (CHAR) == 'R') + +/* Provide a STARTFILE_SPEC appropriate for FreeBSD. Here we add + the magical crtbegin.o file (see crtstuff.c) which provides part + of the support for getting C++ file-scope static object constructed + before entering `main'. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!shared: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \ + %{!p:%{profile:gcrt1.o%s} \ + %{!profile:crt1.o%s}}}} \ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +/* Provide a ENDFILE_SPEC appropriate for FreeBSD. Here we tack on + the magical crtend.o file (see crtstuff.c) which provides part of + the support for getting C++ file-scope static object constructed + before entering `main', followed by a normal "finalizer" file, + `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +/* Provide a LIB_SPEC appropriate for FreeBSD. Just select the appropriate + libc, depending on whether we're doing profiling or need threads support. + (simular to the default, except no -lg, and no -p. */ + +#undef LIB_SPEC +#define LIB_SPEC "%{!shared: \ + %{!pg:%{!pthread:%{!kthread:-lc} \ + %{kthread:-lpthread -lc}} \ + %{pthread:-lc_r}} \ + %{pg:%{!pthread:%{!kthread:-lc_p} \ + %{kthread:-lpthread_p -lc_p}} \ + %{pthread:-lc_r_p}}}" + +/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +#undef LINK_SPEC +#define LINK_SPEC "-m elf_i386 \ + %{Wl,*:%*} \ + %{v:-V} \ + %{assert*} %{R*} %{rpath*} %{defsym*} \ + %{shared:-Bshareable %{h*} %{soname*}} \ + %{!shared: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \ + %{static:-Bstatic}} \ + %{symbolic:-Bsymbolic}" + +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); + +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ +/* On FreeBSD, we do not. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using + libraries compiled with the native cc, so undef it. */ +#undef NO_DOLLAR_IN_LABEL + +/* Use more efficient ``thunks'' to implement C++ vtables. */ +#undef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 2 + +/* Override the default comment-starter of "/". */ +#undef ASM_COMMENT_START +#define ASM_COMMENT_START "#" + +#undef ASM_APP_ON +#define ASM_APP_ON "#APP\n" + +#undef ASM_APP_OFF +#define ASM_APP_OFF "#NO_APP\n" + +#undef SET_ASM_OP +#define SET_ASM_OP ".set" + +/* This is how to output an element of a case-vector that is relative. + This is only used for PIC code. See comments by the `casesi' insn in + i386.md for an explanation of the expression this outputs. */ +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ + fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) + +/* Indicate that jump tables go in the text section. This is + necessary when compiling PIC code. */ +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) + +/* Use stabs instead of DWARF debug format. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +/* Copy this from the svr4 specifications... */ +/* Define the register numbers to be used in Dwarf debugging information. + The SVR4 reference port C compiler uses the following register numbers + in its Dwarf output code: + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) + +/* Tell final.c that we don't need a label passed to mcount. */ + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ +{ \ + if (flag_pic) \ + fprintf (FILE, "\tcall *.mcount@GOT(%%ebx)\n"); \ + else \ + fprintf (FILE, "\tcall .mcount\n"); \ +} + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_UNSIGNED +#define WCHAR_UNSIGNED 0 + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Dunix -D__ELF__ -D__FreeBSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" + +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" + +/* This defines which switch letters take arguments. On FreeBSD, most of + the normal cases (defined in gcc.c) apply, and we also have -h* and + -z* options (for the linker) (comming from svr4). + We also have -R (alias --rpath), no -z, --soname (-h), --assert etc. */ + +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + (DEFAULT_SWITCH_TAKES_ARG (CHAR) \ + || (CHAR) == 'h' \ + || (CHAR) == 'z' \ + || (CHAR) == 'R') + +/* Provide a STARTFILE_SPEC appropriate for FreeBSD. Here we add + the magical crtbegin.o file (see crtstuff.c) which provides part + of the support for getting C++ file-scope static object constructed + before entering `main'. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!shared: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \ + %{!p:%{profile:gcrt1.o%s} \ + %{!profile:crt1.o%s}}}} \ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +/* Provide a ENDFILE_SPEC appropriate for FreeBSD. Here we tack on + the magical crtend.o file (see crtstuff.c) which provides part of + the support for getting C++ file-scope static object constructed + before entering `main', followed by a normal "finalizer" file, + `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +/* Provide a LIB_SPEC appropriate for FreeBSD. Just select the appropriate + libc, depending on whether we're doing profiling or need threads support. + (simular to the default, except no -lg, and no -p. */ + +#undef LIB_SPEC +#define LIB_SPEC "%{!shared: \ + %{!pg:%{!pthread:%{!kthread:-lc} \ + %{kthread:-lpthread -lc}} \ + %{pthread:-lc_r}} \ + %{pg:%{!pthread:%{!kthread:-lc_p} \ + %{kthread:-lpthread_p -lc_p}} \ + %{pthread:-lc_r_p}}}" + +/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +#undef LINK_SPEC +#define LINK_SPEC "-m elf_i386 \ + %{Wl,*:%*} \ + %{v:-V} \ + %{assert*} %{R*} %{rpath*} %{defsym*} \ + %{shared:-Bshareable %{h*} %{soname*}} \ + %{!shared: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \ + %{static:-Bstatic}} \ + %{symbolic:-Bsymbolic}" + +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX + +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + do { \ + output_file_directive (FILE, main_input_filename); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add + the GNU/Linux magical crtbegin.o file (see crtstuff.c) which + provides part of the support for getting C++ file-scope static + object constructed before entering `main'. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!shared: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on + the GNU/Linux magical crtend.o file (see crtstuff.c) which + provides part of the support for getting C++ file-scope static + object constructed before entering `main', followed by a normal + GNU/Linux "finalizer" file, `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +/* This is for -profile to use -lc_p instead of -lc. */ +#undef CC1_SPEC +#define CC1_SPEC "%{profile:-p} \ +%{sun4:} %{target:} \ +%{mcypress:-mcpu=cypress} \ +%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \ +%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \ +" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparc GNU/Linux with ELF)"); + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__sparc__ -Dlinux -Asystem(unix) -Asystem(posix)" + +#undef CPP_SUBTARGET_SPEC +#ifdef USE_GNULIBC_1 +#define CPP_SUBTARGET_SPEC \ +"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" +#else +#define CPP_SUBTARGET_SPEC \ +"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" +#endif + +#undef LIB_SPEC +/* We no longer link with libc_p.a or libg.a by default. If you + want to profile or debug the GNU/Linux C library, please add + -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ +#if 1 +#ifdef USE_GNULIBC_1 +#define LIB_SPEC \ + "%{!shared: %{p:-lgmon} %{pg:-lgmon} %{profile:-lgmon -lc_p} \ + %{!profile:%{!ggdb:-lc} %{ggdb:-lg}}}" +#else +#define LIB_SPEC \ + "%{shared: -lc} \ + %{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \ + %{profile:-lc_p} %{!profile: -lc}}" +#endif +#else +#define LIB_SPEC \ + "%{!shared: \ + %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif + +/* Provide a LINK_SPEC appropriate for GNU/Linux. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +/* If ELF is the default format, we should not use /lib/elf. */ + +#undef LINK_SPEC +#ifdef USE_GNULIBC_1 +#ifndef LINUX_DEFAULT_ELF +#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/elf/ld-linux.so.1} \ + %{!rpath:-rpath /lib/elf/}} %{static:-static}}}" +#else +#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \ + %{static:-static}}}" +#endif +#else +#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \ + %{static:-static}}}" +#endif + +/* The sun bundled assembler doesn't accept -Yd, (and neither does gas). + It's safe to pass -s always, even if -g is not used. */ +#undef ASM_SPEC +#define ASM_SPEC \ + "%{V} %{v:%{!V:-V}} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s %{fpic:-K PIC} %{fPIC:-K PIC}" + +/* Same as sparc.h */ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* We use stabs-in-elf for debugging, because that is what the native + toolchain uses. XXX */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fputs ("\t.local\t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + putc ('\n', (FILE)); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.common" + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d:\n", PREFIX, NUM) + +/* This is how to output a reference to an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABELREF +#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d", PREFIX, NUM) + +/* This is how to store into the string LABEL + the symbol_ref name of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. + This is suitable for output with `assemble_name'. */ + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*.L%s%d", PREFIX, NUM) + + +#if 0 +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. GNU/Linux does not support + long double yet. */ +#define LONG_DOUBLE_TYPE_SIZE 128 +#endif + +/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special + traps available which can get and set the condition codes + reliably. */ +#undef MACHINE_STATE_SAVE +#define MACHINE_STATE_SAVE(ID) \ + unsigned long int ms_flags, ms_saveret; \ + asm volatile("ta 0x20\n\t" \ + "mov %%g1, %0\n\t" \ + "mov %%g2, %1\n\t" \ + : "=r" (ms_flags), "=r" (ms_saveret)); + +#undef MACHINE_STATE_RESTORE +#define MACHINE_STATE_RESTORE(ID) \ + asm volatile("mov %0, %%g1\n\t" \ + "mov %1, %%g2\n\t" \ + "ta 0x21\n\t" \ + : /* no outputs */ \ + : "r" (ms_flags), "r" (ms_saveret)); Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/config/sparc/linux.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/config/elfos.h =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/config/elfos.h (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/config/elfos.h (revision 60969) @@ -0,0 +1,705 @@ +/* elfos.h -- operating system specific defines to be used when + targeting GCC for some generic ELF system + Copyright (C) 1991, 1994, 1995, 1999, 2000 Free Software Foundation, Inc. + Based on svr4.h contributed by Ron Guilmette (rfg@netcom.com). + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* For the sake of libgcc2.c, indicate target supports atexit. */ +#define HAVE_ATEXIT + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared: \ + %{!symbolic: \ + %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\ + crtbegin.o%s" + +/* Attach a special .ident directive to the end of the file to identify + the version of GCC which compiled this code. The format of the + .ident string is patterned after the ones produced by native svr4 + C compilers. */ + +#define IDENT_ASM_OP ".ident" + +#define ASM_FILE_END(FILE) \ +do { \ + if (!flag_no_ident) \ + fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \ + IDENT_ASM_OP, version_string); \ + } while (0) + +/* Output #ident as a .ident. */ + +#define ASM_OUTPUT_IDENT(FILE, NAME) \ + fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME); + +/* Use periods rather than dollar signs in special g++ assembler names. */ + +#define NO_DOLLAR_IN_LABEL + +/* Writing `int' for a bitfield forces int alignment for the structure. */ + +#define PCC_BITFIELD_TYPE_MATTERS 1 + +/* Implicit library calls should use memcpy, not bcopy, etc. */ + +#define TARGET_MEM_FUNCTIONS + +/* Handle #pragma weak and #pragma pack. */ + +#define HANDLE_SYSV_PRAGMA + +/* System V Release 4 uses DWARF debugging info. */ + +#define DWARF_DEBUGGING_INFO + +/* All ELF targets can support DWARF-2. */ + +#define DWARF2_DEBUGGING_INFO + +/* Also allow them to support STABS debugging. */ + +#include "dbxelf.h" + +/* The GNU tools operate better with stabs. Since we don't have + any native tools to be compatible with, default to stabs. */ + +#ifndef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +#endif + +#undef ASM_BYTE_OP +#define ASM_BYTE_OP ".byte" + +#undef SET_ASM_OP +#define SET_ASM_OP ".set" + +/* This is how to begin an assembly language file. Most svr4 assemblers want + at least a .file directive to come first, and some want to see a .version + directive come right after that. Here we just establish a default + which generates only the .file directive. If you need a .version + directive for any specific target, you should override this definition + in the target-specific file which includes this one. */ + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + output_file_directive ((FILE), main_input_filename) + +/* This is how to allocate empty space in some section. The .zero + pseudo-op is used for this on most svr4 assemblers. */ + +#define SKIP_ASM_OP ".zero" + +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t%s\t%u\n", SKIP_ASM_OP, (SIZE)) + +/* This is how to output a reference to a user-level label named NAME. + `assemble_name' uses this. + + For System V Release 4 the convention is *not* to prepend a leading + underscore onto user-level symbol names. */ + +#undef ASM_OUTPUT_LABELREF +#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "%s", NAME) + +/* This is how to output an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. + + For most svr4 systems, the convention is that any symbol which begins + with a period is not put into the linker symbol table by the assembler. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \ +do { \ + fprintf (FILE, ".%s%d:\n", PREFIX, NUM); \ +} while (0) + +/* This is how to store into the string LABEL + the symbol_ref name of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. + This is suitable for output with `assemble_name'. + + For most svr4 systems, the convention is that any symbol which begins + with a period is not put into the linker symbol table by the assembler. */ + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ +do { \ + sprintf (LABEL, "*.%s%d", PREFIX, NUM); \ +} while (0) + +/* Output the label which precedes a jumptable. Note that for all svr4 + systems where we actually generate jumptables (which is to say every + svr4 target except i386, where we use casesi instead) we put the jump- + tables into the .rodata section and since other stuff could have been + put into the .rodata section prior to any given jumptable, we have to + make sure that the location counter for the .rodata section gets pro- + perly re-aligned prior to the actual beginning of the jump table. */ + +#define ALIGN_ASM_OP ".align" + +#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL +#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ + ASM_OUTPUT_ALIGN ((FILE), 2); +#endif + +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \ + do { \ + ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE) \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \ + } while (0) + +/* The standard SVR4 assembler seems to require that certain builtin + library routines (e.g. .udiv) be explicitly declared as .globl + in each assembly file where they are referenced. */ + +#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ + ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0)) + +/* This says how to output assembler code to declare an + uninitialized external linkage data object. Under SVR4, + the linker seems to want the alignment of data objects + to depend on their types. We do exactly that here. */ + +#define COMMON_ASM_OP ".comm" + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ +} while (0) + +/* This says how to output assembler code to declare an + uninitialized internal linkage data object. Under SVR4, + the linker seems to want the alignment of data objects + to depend on their types. We do exactly that here. */ + +#define LOCAL_ASM_OP ".local" + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "\t%s\t", LOCAL_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), "\n"); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +/* This is the pseudo-op used to generate a 32-bit word of data with a + specific value in some section. This is the same for all known svr4 + assemblers. */ + +#define INT_ASM_OP ".long" + +/* This is the pseudo-op used to generate a contiguous sequence of byte + values from a double-quoted string WITHOUT HAVING A TERMINATING NUL + AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */ + +#undef ASCII_DATA_ASM_OP +#define ASCII_DATA_ASM_OP ".ascii" + +/* Support const sections and the ctors and dtors sections for g++. + Note that there appears to be two different ways to support const + sections at the moment. You can either #define the symbol + READONLY_DATA_SECTION (giving it some code which switches to the + readonly data section) or else you can #define the symbols + EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and + SELECT_RTX_SECTION. We do both here just to be on the safe side. */ + +#define USE_CONST_SECTION 1 + +#define CONST_SECTION_ASM_OP ".section\t.rodata" + +/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. + + Note that we want to give these sections the SHF_WRITE attribute + because these sections will actually contain data (i.e. tables of + addresses of functions in the current root executable or shared library + file) and, in the case of a shared library, the relocatable addresses + will have to be properly resolved/relocated (and then written into) by + the dynamic linker when it actually attaches the given shared library + to the executing process. (Note that on SVR4, you may wish to use the + `-z text' option to the ELF linker, when building a shared library, as + an additional check that you are doing everything right. But if you do + use the `-z text' option when building a shared library, you will get + errors unless the .ctors and .dtors sections are marked as writable + via the SHF_WRITE attribute.) */ + +#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\"" +#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\"" + +/* On svr4, we *do* have support for the .init and .fini sections, and we + can put stuff in there to be executed before and after `main'. We let + crtstuff.c and other files know this by defining the following symbols. + The definitions say how to change sections to the .init and .fini + sections. This is the same for all known svr4 assemblers. */ + +#define INIT_SECTION_ASM_OP ".section\t.init" +#define FINI_SECTION_ASM_OP ".section\t.fini" + +/* A default list of other sections which we might be "in" at any given + time. For targets that use additional sections (e.g. .tdesc) you + should override this definition in the target-specific file which + includes this file. */ + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_const, in_ctors, in_dtors + +/* A default list of extra section function definitions. For targets + that use additional sections (e.g. .tdesc) you should override this + definition in the target-specific file which includes this file. */ + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CONST_SECTION_FUNCTION \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +#define READONLY_DATA_SECTION() const_section () + +extern void text_section (); + +#define CONST_SECTION_FUNCTION \ +void \ +const_section () \ +{ \ + if (!USE_CONST_SECTION) \ + text_section(); \ + else if (in_section != in_const) \ + { \ + fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \ + in_section = in_const; \ + } \ +} + +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +/* Switch into a generic section. + This is currently only used to support section attributes. */ + +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ +do { \ + static struct section_info \ + { \ + struct section_info *next; \ + char *name; \ + enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \ + } *sections; \ + struct section_info *s; \ + char *mode; \ + enum sect_enum type; \ + \ + for (s = sections; s; s = s->next) \ + if (!strcmp (NAME, s->name)) \ + break; \ + \ + if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \ + type = SECT_EXEC, mode = "ax"; \ + else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \ + type = SECT_RO, mode = "a"; \ + else \ + type = SECT_RW, mode = "aw"; \ + \ + if (s == 0) \ + { \ + s = (struct section_info *) xmalloc (sizeof (struct section_info)); \ + s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \ + strcpy (s->name, NAME); \ + s->type = type; \ + s->next = sections; \ + sections = s; \ + fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, mode); \ + } \ + else \ + { \ + if (DECL && s->type != type) \ + error_with_decl (DECL, "%s causes a section type conflict"); \ + \ + fprintf (FILE, ".section\t%s\n", NAME); \ + } \ +} while (0) + +#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1) +#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL)) +#define UNIQUE_SECTION(DECL,RELOC) \ +do { \ + int len; \ + char *name, *string, *prefix; \ + \ + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \ + \ + if (! DECL_ONE_ONLY (DECL)) \ + { \ + if (TREE_CODE (DECL) == FUNCTION_DECL) \ + prefix = ".text."; \ + else if (DECL_READONLY_SECTION (DECL, RELOC)) \ + prefix = ".rodata."; \ + else \ + prefix = ".data."; \ + } \ + else if (TREE_CODE (DECL) == FUNCTION_DECL) \ + prefix = ".gnu.linkonce.t."; \ + else if (DECL_READONLY_SECTION (DECL, RELOC)) \ + prefix = ".gnu.linkonce.r."; \ + else \ + prefix = ".gnu.linkonce.d."; \ + \ + len = strlen (name) + strlen (prefix); \ + string = alloca (len + 1); \ + sprintf (string, "%s%s", prefix, name); \ + \ + DECL_SECTION_NAME (DECL) = build_string (len, string); \ +} while (0) +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ + do { \ + ctors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +/* A C statement (sans semicolon) to output an element in the table of + global destructors. */ +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ + do { \ + dtors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +/* A C statement or statements to switch to the appropriate + section for output of DECL. DECL is either a `VAR_DECL' node + or a constant of some sort. RELOC indicates whether forming + the initial value of DECL requires link-time relocations. */ + +#define SELECT_SECTION(DECL,RELOC) \ +{ \ + if (TREE_CODE (DECL) == STRING_CST) \ + { \ + if (! flag_writable_strings) \ + const_section (); \ + else \ + data_section (); \ + } \ + else if (TREE_CODE (DECL) == VAR_DECL \ + || TREE_CODE (DECL) == CONSTRUCTOR) \ + { \ + if ((flag_pic && RELOC) \ + || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ + || !DECL_INITIAL (DECL) \ + || (DECL_INITIAL (DECL) != error_mark_node \ + && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \ + data_section (); \ + else \ + const_section (); \ + } \ + else \ + const_section (); \ +} + +/* A C statement or statements to switch to the appropriate + section for output of RTX in mode MODE. RTX is some kind + of constant in RTL. The argument MODE is redundant except + in the case of a `const_int' rtx. Currently, these always + go into the const section. */ + +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) const_section() + +/* Define the strings used for the special svr4 .type and .size directives. + These strings generally do not vary from one system running svr4 to + another, but if a given system (e.g. m88k running svr) needs to use + different pseudo-op names for these, they may be overridden in the + file which includes this one. */ + +#define TYPE_ASM_OP ".type" +#define SIZE_ASM_OP ".size" + +/* This is how we tell the assembler that a symbol is weak. */ + +#define ASM_WEAKEN_LABEL(FILE,NAME) \ + do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \ + fputc ('\n', FILE); } while (0) + +/* The following macro defines the format used to output the second + operand of the .type assembler directive. Different svr4 assemblers + expect various different forms for this operand. The one given here + is just a default. You may need to override it in your machine- + specific tm.h file (depending upon the particulars of your assembler). */ + +#define TYPE_OPERAND_FMT "@%s" + +/* Write the extra assembler code needed to declare a function's result. + Most svr4 assemblers don't require any special declaration of the + result value, but there are exceptions. */ + +#ifndef ASM_DECLARE_RESULT +#define ASM_DECLARE_RESULT(FILE, RESULT) +#endif + +/* These macros generate the special .type and .size directives which + are used to set the corresponding fields of the linker symbol table + entries in an ELF object file under SVR4. These macros also output + the starting labels for the relevant functions/objects. */ + +/* Write the extra assembler code needed to declare a function properly. + Some svr4 assemblers need to also have something extra said about the + function's return value. We allow for that here. */ + +#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ + do { \ + fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + putc (',', FILE); \ + fprintf (FILE, TYPE_OPERAND_FMT, "function"); \ + putc ('\n', FILE); \ + ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ + ASM_OUTPUT_LABEL(FILE, NAME); \ + } while (0) + +/* Write the extra assembler code needed to declare an object properly. */ + +#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ + do { \ + fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + putc (',', FILE); \ + fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ + putc ('\n', FILE); \ + size_directive_output = 0; \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + ASM_OUTPUT_LABEL(FILE, NAME); \ + } while (0) + +/* Output the size directive for a decl in rest_of_decl_compilation + in the case where we did not do so before the initializer. + Once we find the error_mark_node, we know that the value of + size_directive_output was set + by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ + +#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ +do { \ + char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ + && ! AT_END && TOP_LEVEL \ + && DECL_INITIAL (DECL) == error_mark_node \ + && !size_directive_output) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, name); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + } while (0) + +/* This is how to declare the size of a function. */ + +#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ + do { \ + if (!flag_inhibit_size_directive) \ + { \ + char label[256]; \ + static int labelno; \ + labelno++; \ + ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \ + fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, (FNAME)); \ + fprintf (FILE, ","); \ + assemble_name (FILE, label); \ + fprintf (FILE, "-"); \ + assemble_name (FILE, (FNAME)); \ + putc ('\n', FILE); \ + } \ + } while (0) + +/* A table of bytes codes used by the ASM_OUTPUT_ASCII and + ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table + corresponds to a particular byte value [0..255]. For any + given byte value, if the value in the corresponding table + position is zero, the given character can be output directly. + If the table value is 1, the byte must be output as a \ooo + octal escape. If the tables value is anything else, then the + byte value should be output as a \ followed by the value + in the table. Note that we can use standard UN*X escape + sequences for many control characters, but we don't use + \a to represent BEL because some svr4 assemblers (e.g. on + the i386) don't know about that. Also, we don't use \v + since some versions of gas, such as 2.2 did not accept it. */ + +#define ESCAPES \ +"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1" + +/* Some svr4 assemblers have a limit on the number of characters which + can appear in the operand of a .string directive. If your assembler + has such a limitation, you should define STRING_LIMIT to reflect that + limit. Note that at least some svr4 assemblers have a limit on the + actual number of bytes in the double-quoted string, and that they + count each character in an escape sequence as one byte. Thus, an + escape sequence like \377 would count as four bytes. + + If your target assembler doesn't support the .string directive, you + should define this to zero. +*/ + +#define STRING_LIMIT ((unsigned) 256) + +#define STRING_ASM_OP ".string" + +/* The routine used to output NUL terminated strings. We use a special + version of this for most svr4 targets because doing so makes the + generated assembly code more compact (and thus faster to assemble) + as well as more readable, especially for targets like the i386 + (where the only alternative is to output character sequences as + comma separated lists of numbers). */ + +#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \ + do \ + { \ + register unsigned char *_limited_str = (unsigned char *) (STR); \ + register unsigned ch; \ + fprintf ((FILE), "\t%s\t\"", STRING_ASM_OP); \ + for (; ch = *_limited_str; _limited_str++) \ + { \ + register int escape; \ + switch (escape = ESCAPES[ch]) \ + { \ + case 0: \ + putc (ch, (FILE)); \ + break; \ + case 1: \ + fprintf ((FILE), "\\%03o", ch); \ + break; \ + default: \ + putc ('\\', (FILE)); \ + putc (escape, (FILE)); \ + break; \ + } \ + } \ + fprintf ((FILE), "\"\n"); \ + } \ + while (0) + +/* The routine used to output sequences of byte values. We use a special + version of this for most svr4 targets because doing so makes the + generated assembly code more compact (and thus faster to assemble) + as well as more readable. Note that if we find subparts of the + character sequence which end with NUL (and which are shorter than + STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */ + +#undef ASM_OUTPUT_ASCII +#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \ + do \ + { \ + register unsigned char *_ascii_bytes = (unsigned char *) (STR); \ + register unsigned char *limit = _ascii_bytes + (LENGTH); \ + register unsigned bytes_in_chunk = 0; \ + for (; _ascii_bytes < limit; _ascii_bytes++) \ + { \ + register unsigned char *p; \ + if (bytes_in_chunk >= 60) \ + { \ + fprintf ((FILE), "\"\n"); \ + bytes_in_chunk = 0; \ + } \ + for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \ + continue; \ + if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \ + { \ + if (bytes_in_chunk > 0) \ + { \ + fprintf ((FILE), "\"\n"); \ + bytes_in_chunk = 0; \ + } \ + ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \ + _ascii_bytes = p; \ + } \ + else \ + { \ + register int escape; \ + register unsigned ch; \ + if (bytes_in_chunk == 0) \ + fprintf ((FILE), "\t%s\t\"", ASCII_DATA_ASM_OP); \ + switch (escape = ESCAPES[ch = *_ascii_bytes]) \ + { \ + case 0: \ + putc (ch, (FILE)); \ + bytes_in_chunk++; \ + break; \ + case 1: \ + fprintf ((FILE), "\\%03o", ch); \ + bytes_in_chunk += 4; \ + break; \ + default: \ + putc ('\\', (FILE)); \ + putc (escape, (FILE)); \ + bytes_in_chunk += 2; \ + break; \ + } \ + } \ + } \ + if (bytes_in_chunk > 0) \ + fprintf ((FILE), "\"\n"); \ + } \ + while (0) + +/* All SVR4 targets use the ELF object file format. */ +#define OBJECT_FORMAT_ELF Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/config/elfos.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/config/linux.h =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/config/linux.h (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/config/linux.h (revision 60969) @@ -0,0 +1,115 @@ +/* Definitions for Linux-based GNU systems with ELF format + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Eric Youngdale. + Modified for stabs-in-ELF by H.J. Lu (hjl@lucon.org). + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Don't assume anything about the header files. */ +#define NO_IMPLICIT_EXTERN_C + +#undef HAVE_ATEXIT +#define HAVE_ATEXIT + +/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is. + For now, we play safe. It may change later. */ + +#if 0 +#undef MULTIBYTE_CHARS +#define MULTIBYTE_CHARS 1 +#endif + +#undef ASM_APP_ON +#define ASM_APP_ON "#APP\n" + +#undef ASM_APP_OFF +#define ASM_APP_OFF "#NO_APP\n" + +#define SET_ASM_OP ".set" + +/* Use stabs instead of DWARF debug format. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +#include "svr4.h" + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX + +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + do { \ + output_file_directive (FILE, main_input_filename); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add + the GNU/Linux magical crtbegin.o file (see crtstuff.c) which + provides part of the support for getting C++ file-scope static + object constructed before entering `main'. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!shared: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \ + %{!p:%{profile:gcrt1.o%s} \ + %{!profile:crt1.o%s}}}} \ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on + the GNU/Linux magical crtend.o file (see crtstuff.c) which + provides part of the support for getting C++ file-scope static + object constructed before entering `main', followed by a normal + GNU/Linux "finalizer" file, `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +/* This is for -profile to use -lc_p instead of -lc. */ +#ifndef CC1_SPEC +#define CC1_SPEC "%{profile:-p}" +#endif + +#ifndef USE_GNULIBC_1 +#undef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 2 +#endif + +#undef LIB_SPEC +/* We no longer link with libc_p.a or libg.a by default. If you + want to profile or debug the GNU/Linux C library, please add + -profile or -ggdb to LDFLAGS at the link time, respectively. */ +#if 1 +#ifdef USE_GNULIBC_1 +#define LIB_SPEC \ + "%{!shared: %{p:-lgmon} %{pg:-lgmon} %{profile:-lgmon -lc_p} \ + %{!profile:%{!ggdb:-lc} %{ggdb:-lg}}}" +#else +#define LIB_SPEC \ + "%{shared: -lc} \ + %{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \ + %{profile:-lc_p} %{!profile: -lc}}" +#endif +#else +#define LIB_SPEC \ + "%{!shared: \ + %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/config/linux.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/ChangeLog =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/ChangeLog (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/ChangeLog (revision 60969) @@ -0,0 +1,16207 @@ +2000-03-08 Nathan Sidwell + + * exception.cc (__cp_pop_exception): Cleanup the original object. + +1999-11-13 Jason Merrill + + * rtti.c (get_tinfo_fn_unused): Split out from get_tinfo_fn. + * class.c (set_rtti_entry): Use it. + +Wed Apr 12 00:45:49 2000 Jeffrey A Law (law@cygnus.com) + + 2000-02-03 + * call.c (add_function_candidate): Do not add vlist ctor into + candidates in compatibility mode. + (build_user_type_conversion_1): Add LOOKUP_HAS_VLIST when adding + vlist. + (convert_like): Likewise. + (build_over_call): Skip vlist only if it is mentioned in flags. + (build_new_method_call): Do not add vlist in compatibility mode, + except for dtors. + * cp-tree.h (flag_vtable_thunks): Has now four possible values. + (DECL_VLIST_CTOR_WRAPPER_P, DECL_VLIST_CTOR_WRAPPED): New macros. + (in_charge_identifier): Declare external. + * decl.c (xref_basetypes): Check for vtable_thunks >=2. + (finish_dtor): Use bit 2 of in_chrg. + (finish_function): Do not finish vlist ctor wrappers. + * decl2.c (flag_vtable_thunks_compat): New variable. + (lang_decode_option): Set it accordingly. + (maybe_retrofit_in_chrg): Call make_vlist_ctor_wrapper. + * init.c (build_base_dtor_call): Pass 4 in in_chrg. + (no_vlist_base_init): New function. + (expand_default_init): Do not pass vlist in compatibility mode. + Try to call old base ctor if new one was not generated. + (build_new_1): Do not pass vlist in compatibility mode. + * method.c (get_id_2): Do not put _Vlist into dtor name in + compatibility mode. + (make_vlist_ctor_wrapper, emit_vlist_ctor_wrapper): New functions. + (synthesize_method): Call emit_vlist_ctor_wrapper. + * pt.c (instantiate_class_template): Check for vtable_thunks >=2. + + Sat Nov 13 15:48:59 1999 H.J. Lu + * init.c (finish_dtor): Call mark_all_temps_used () before + declaring vlist. + + Tue Nov 9 15:01:57 1999 H.J. Lu + * init.c (construct_virtual_bases): Update. + (expand_cleanup_for_base): Update. + + Tue Nov 9 08:25:04 1999 H.J. Lu + * init.c (construct_virtual_bases): Update. + (expand_cleanup_for_base): Take vlist parameter. + (emit_base_init): Pass vlist to expand_cleanup_for_base. + (construct_virtual_bases): Likewise. + + 1999-05-02 Martin von Löwis + * class.c (prepare_ctor_vtable, finish_one_ctor_vtable, + prepend_ctor_vfields_for_vbase, finish_ctor_vtables_for_vbases, + finish_ctor_vtables_1, prepend_vbase_vfields, + finish_ctor_vtables): New functions. + (finish_struct_1): Call finish_ctor_vtables. + * cp-tree.h (TYPE_USES_PVBASES): New macro. + (constructor_for_vbase_attr): Widen to two bits. + (CONSTRUCTOR_FOR_VBASE, CONSTRUCTOR_FOR_PVBASE, + DESTRUCTOR_FOR_PVBASE): New macros. + (DECL_CONSTRUCTOR_FOR_VBASE_P): Adopt to new enumeration. + (DECL_CONSTRUCTOR_FOR_VBASE): New macro. + (DECL_CONSTRUCTOR_FOR_PVBASE_P, DECL_DESTRUCTOR_FOR_PVBASE_P): New + macros. + (vlist_identifier, vlist_type_node, vlist_zero_node): Declare. + (VCTABLE_NAME, VLIST_NAME_FORMAT, VLIST_NAME, VLIST1_NAME, + VLIST_TYPE_NAME): New macros. + (LOOKUP_HAS_VLIST): New macro. + (build_base_dtor_call, init_vlist): Declare. + (build_destructor_name): Add int argument. + * decl.c (vlist_identifier, vlist_type_node, vlist_zero_node): + Define. + (init_decl_processing): Initialize them. + (grokdeclarator): Handle vlist argument. + (copy_args_p): Likewise. + (grok_ctor_properties): Don't try to skip initial int for + templates. Skip vlist if available. + (xref_basetypes): Set TYPE_USES_PVBASES. + (finish_dtor, finish_ctor): New functions, moved out of ... + (finish_function): ... here. + * decl2.c (lang_decode_option): Set flag_vtable_thunks explicitly. + (maybe_retrofit_in_chrg): Retrofit __vlist parameter. + (grokclassfn): Pass pvbase flag into mangled name. + * init.c (build_base_dtor_call): New function. + (build_partial_cleanup_for): Call it. + (pvbasecount, init_vlist, ): New functions. + (emit_base_init): Process vlist argument. + (expand_aggr_vbase_init_1): Likewise. + (expand_aggr_vbase_init): Likewise. + (expand_default_init): Likewise. + (build_new_1): Pass null vlist argument. + (build_delete): Likewise. Call build_base_dtor_call. + * method.c (process_overload_item): Mangle _Vlist specially. + (build_base_path, get_vlist_vtable_id): New functions. + (build_destructor_name): Potentially mangle _Vlist into it. + (do_build_copy_constructor): Skip vlist argument. + (synthesize_method): Likewise. + * pt.c (has_pvbases_p): New function. + (instantiate_class_template): Call it. + (tsubst_decl): Retrofit before mangling. Pass pvbase_p to + destructor mangling. + * search.c (expand_direct_vtbls_init_thunks): New function. + (expand_indirect_vtbls_init_thunks): New function. + (expand_indirect_vtbls_init): Call it. + * call.c (add_function_candidate): Process vlist argument. + (build_user_type_conversion_1): Add vlist argument. + (convert_like): Likewise. + (build_over_call): Likewise. + (build_new_method_call): Likewise. + +2000-02-18 Martin von Loewis + + * typeck2.c (my_friendly_abort): Use GCCBUGURL. + +1999-11-01 Jason Merrill + + * decl2.c (maybe_make_one_only): Always make things comdat on + ELF targets, too. + +Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) + + * gcc-2.95.2 Released. + +1999-09-06 Mark Mitchell + + * pt.c (tsubst): Back out 1999-08-06 patch. Use fold and + decl_constant_value to simplify array bounds. + +1999-08-19 Jason Merrill + + * cp-tree.h: Declare flag_use_repository. + * pt.c (do_decl_instantiation): Don't complain about duplicate + instantiation with -frepo. + (do_type_instantiation): Likewise. + +1999-08-14 Jason Merrill + + * decl2.c (lookup_arg_dependent): Note that we've already checked + the current namespace. + +Mon Aug 16 01:29:24 PDT 1999 Jeff Law (law@cygnus.com) + + * gcc-2.95.1 Released. + +1999-08-12 Mark Mitchell + + * decl2.c (lang_decode_option): Deprecate signatures. + +1999-08-11 Martin v. Loewis + + * lex.c (do_identifier): If we find a hidden type after a global + was selected already, continue using the global. + +1999-08-10 Martin v. Loewis + + * decl2.c (set_decl_namespace): Do not complain about non-matching + decls if processing a template. + +1999-08-09 Jason Merrill + + * parse.y (function_try_block): Call end_protect_partials + before expand_start_all_catch. + +1999-08-06 Jason Merrill + + * pt.c (maybe_get_template_decl_from_type_decl): Make sure that + we're looking at a class. + + * decl.c (lookup_name_real): Set the complain flag if we're + looking for a namespace member. + + * decl.c (pushdecl): Only give an error for shadowing a parm + from *this* function. + + * decl2.c (build_expr_from_tree, case METHOD_CALL_EXPR): Only + build_expr_from_tree on the args of a TEMPLATE_ID_EXPR. + + * class.c (mark_overriders): Fix order of args to overrides. + (warn_hidden): Likewise. Fix for having virtual and non-virtual + functions with the same name. + + * cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro. + * typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for + virtual functions and MI. Simplify. + + * typeck.c (c_expand_return): Downgrade pedwarn about returning NULL + from op new to warning. + + * decl2.c (reparse_absdcl_as_casts): Don't warn about old-style + casts in system headers or extern "C" blocks. + + * pt.c (do_decl_instantiation): Downgrade duplicate instantiation + errors to pedwarn. + + * error.c (dump_type_real): Handle TREE_LIST again. + + * typeck.c (comp_target_parms): Don't complain about + converting from () to (...) if !flag_strict_prototype. + + * class.c (instantiate_type): Downgrade errors for object-dependent + memfn refs to pedwarn. + +1999-08-06 Alexandre Oliva + + * pt.c (tsubst): Use build_index_type to build in-template array + index type. Fixes g++.oliva/dwarf1.C. + * decl.c (grokdeclarator): Likewise, just for consistency, as it + doesn't seem to trigger the bug without it. + +Thu Aug 5 02:40:42 1999 Jeffrey A Law (law@cygnus.com) + + * typeck2.c: Update URLs and mail addresses. + +1999-08-03 Mumit Khan + + * decl.c (start_decl): Set attributes before duplicate_decls call. + +Wed Jul 28 21:39:31 PDT 1999 Jeff Law (law@cygnus.com) + + * gcc-2.95 Released. + +Sun Jul 25 15:24:21 1999 Jeffrey A Law (law@cygnus.com) + + * g++FAQ.texi: Deleted per Joe Buck's request. + * Makefile.in: Corresponding changes. + +Sat Jul 17 23:50:47 1999 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (INTERFACE): Bump to 2. + +1999-07-17 Alexandre Oliva + + * typeck2.c (my_friendly_abort): Updated URL with bug reporting + instructions to gcc.gnu.org. Removed e-mail address. + +1999-07-15 Mark Mitchell + + * pt.c (check_default_tmpl_args): Handle friends defined in the + class just like member functions defined in the class. + +Thu Jul 15 01:26:49 1999 H.J. Lu + + * decl.c (duplicate_decls): Relax restriction for exception + checks on duplicate symbols. + +1999-07-07 Jason Merrill + + * decl.c (grokdeclarator): Update the names of all variants when + de-anonymizing. + +Wed Jul 7 01:26:47 1999 Alexandre Oliva + + * decl2.c (mark_vtable_entries): Fix check for rtti offset. + +1999-06-26 Richard Henderson + + * decl.c (cp_finish_decl): Fix typo in cp_warning_at call. + +1999-06-21 Mark Mitchell + + * init.c (expand_aggr_vbase_init): Rename to + construct_virtual_bases. Conditionalize construction here, + rather than ... + (emit_base_init): Here. + +1999-06-19 Mark Mitchell + + * semantics.c (finish_asm_statement): Apply decay conversions to + input operands. + + * decl.c (expand_static_init): When building an anonymous function + for use with atexit, compute its body before and after entering + the function. + +1999-06-18 Mark Mitchell + + * init.c (expand_aggr_vbase_init): Add flag parameter. + (build_partial_cleanup_for): Remove, inlining into .. + (expand_cleanup_for_base): ... here. Take flag parameter. + (emit_base_init): Pass the in_chrg parameter to + emit_aggr_vbase_init. + (emit_aggr_vbase_init): Pass it to expand_cleanup_for_base. + +1999-06-16 Mark Mitchell + + * decl2.c (import_export_decl): Use same_type_p, rather than + relying on pointer-equality for types. + + * method.c (do_build_copy_constructor): Simplify. + + * call.c (build_method_call): Remove bogus code for two-argument + delete. + * init.c (build_new_1): Expand on comment, and remove dead code. + + * init.c (expand_cleanup_for_base): New function, split out + from ... + (emit_base_init): Here. + (expand_aggr_vbase_init): Use it. + +1999-06-15 Mark Mitchell + + * cp-tree.h (class_cache_firstobj): Declare. + (maybe_push_cache_obstack): Rename to push_cache_obstack. + * class.c (permanent_obstack): Remove declaration. + (class_cache_firstobj): Make it global. + (add_method): Don't use permanent_obstack directly. + (pushclass): Only free the class_cache_obstack if we know how far + back to free it. + (maybe_push_cache_obstack): Rename to push_cache_obstack. + * decl.c: Remove dead comment. + (saved_scope): Add class_cache_firstobj. + (push_to_top_level): Save it. + (pop_from_top_level): Restore it. + (push_class_level_binding): Use push_cache_obstack, not + maybe_push_cache_obstack. + * search.c (push_class_decls): Likewise. + +1999-06-14 Nathan Sidwell + + * call.c (build_new_op): Remove REF_BIND from all operands. + +1999-06-07 Mark Mitchell + + * search.c (convert_pointer_to_single_level): Reimplement without + using get_binfo. + +1999-06-06 Mark Mitchell + + * method.c (is_back_referenceable_type): Back-reference bools when + not squangling. + +1999-06-04 Jason Merrill + + * semantics.c (finish_if_stmt_cond): Copy cond to permanent_obstack. + (finish_while_stmt_cond, finish_do_stmt, finish_for_cond): Likewise. + +1999-05-30 Mark Mitchell + + * lex.c (make_lang_type): Create TYPE_BINFO for + TEMPLATE_TYPE_PARMs just like for non-template types. + +1999-05-28 Nathan Sidwell + + * decl.c (complete_array_type): Allocate off same obstack. Fix + DO_DEFAULT comment to match reality. + +1999-05-22 Mark Mitchell + + * tree.c (mapcar): Handle NON_LVALUE_EXPR. + +1999-05-21 Mark Mitchell + + * typeck.c (build_ptrmemfunc): Handle PTRMEM_CSTs carefully to + reveal optimization opportunities. + +1999-05-20 Mark Mitchell + + * decl.c (grokdeclarator): Don't treat [] as indicating a + zero-sized array in a typedef. + + * call.c (build_object_call): Don't look at DECL_NAME for a type. + (pt.c): Or CP_TYPE_QUALS for an ERROR_MARK. + (typeck.c): Or TYPE_MAIN_VARIANT for a type. + +1999-05-20 Jason Merrill + + * tree.c (lvalue_p_1): A NOP_EXPR can be an lvalue. + (build_cplus_new): Make sure that what we return is of the right type. + +1999-05-20 Mark Mitchell + + * cp-tree.h (make_ptrmem_cst): New function. + * expr.c (cplus_expand_constant): Split out from ... + (cplus_expand_expr): Here. Use cplus_expand_constant. + (init_cplus_expand): Set lang_expand_constant. + * pt.c (convert_nontype_argument): Use make_ptrmem_cst. + * tree.c (make_ptrmem_cst): Define. + * typeck.c (unary_complex_lvalue): Use make_ptrmem_cst. + * typeck2.c (initializer_constant_valid_p): Use make_ptrmem_cst. + +1999-05-19 Mark Mitchell + + * decl2.c (start_static_storage_duration_function): Fix comment. + (finish_file): Create static storage duration functions lazily. + +Wed May 19 02:50:53 1999 Arvind Sankar + + * gxxint.texi: Fix typo. + +1999-05-18 Jason Merrill + + * call.c (joust): Compare the types of the conv ops, not the + target types of the conversions. + +Tue May 18 00:21:34 1999 Zack Weinberg + + * lang-specs.h: Define __GNUC__ and __GNUC_MINOR__ only if -no-gcc + was not given. + +1999-05-17 Mark Mitchell + + * cp-tree.def (TEMPLATE_ID_EXPR): Update documentation. + * decl.c (grokfndecl): Don't allow inline declarations of friend + template specializations, or friend template specializations with + default arguments. + * pt.c (tsubst): Handle substitution into array types that does + not yield a fixed upper bound, even when not processing a + template. + (tsubst_copy): Deal with the fact that the second operand to a + TEMPLATE_ID_EXPR may be NULL_TREE, a TREE_LIST, or a TREE_VEC. + * search.c (marked_pushdecls_p): Don't descend into + TEMPLATE_TYPE_PARMs and the like. + (unmarked_pushdecls_p): Likewise. + + * call.c (build_over_call): Don't throw away + initializations/copies of empty classes; use MODIFY_EXPR and + INIT_EXPR as for non-empty classes. + * class.c (finish_struct_1): Put the padding byte for an empty + class on the TYPE_NONCOPIED_PARTS list for the class. + +1999-05-16 Mark Mitchell + + * decl2.c (build_expr_from_tree): Handle COMPONENT_REFs that + indicate a reference to a field that is a qualified name. + +1999-05-16 Jason Merrill + + * decl2.c (finish_objects): Don't use .?tors.* if we don't have + ASM_OUTPUT_CONSTRUCTOR. + + * friend.c (do_friend): Add attrlist arg. Remove support for + getting a non-decl as 'decl'. + * decl.c (grokfndecl): Remove attrlist arg. Don't set attrs or + rtl. + (grokdeclarator): Adjust. + * cp-tree.h: Adjust. + +1999-05-16 Mark Mitchell + + * cp-tree.h (permanent_p): New function. + * init.c (build_new_1): Use mapcar, not copy_node, to copy a + possibly complex tree node. + * tree.c (mapcar): Adjust comments, and follow coding standards in + conditional. + (permanent_p): New function. + +1999-05-13 Per Bothner + + * class.c (push_lang_context): Turn off DECL_IGNORED_P for + primitive Java types, if we actually see `extern "Java"'. + +1999-05-10 18:21 -0400 Zack Weinberg + + * lang-specs.h: Pass -$ to the preprocessor. + +1999-05-10 Jason Merrill + + * init.c (build_offset_ref): Wrap baselinks in OFFSET_REF, too. + Don't bother wrapping an OFFSET_TYPE around unknown_type_node. + (resolve_offset_ref): Don't handle a raw baselink. + * cvt.c (build_expr_type_conversion): Likewise. + * typeck.c (decay_conversion, build_c_cast, convert_for_assignment, + convert_for_initialization): Likewise. + * class.c (instantiate_type): Handle seeing a baselink under an + OFFSET_REF. + * error.c (dump_expr): Likewise. + * pt.c (for_each_template_parm): Likewise. + (resolve_overloaded_unification): Likewise. + * tree.c (is_overloaded_fn, really_overloaded_fn): Likewise. + * typeck.c (expr_sizeof): Also complain about other permutations + of overloaded functions. + +1999-05-07 Jason Merrill + + * init.c (resolve_offset_ref): Don't return a raw method. + Use BASELINK_P. + * typeck.c (decay_conversion): Don't handle a raw method. + Resolve all OFFSET_REFs. + (get_member_function_from_ptrfunc): 0 is a valid vtable index. + (build_binary_op_nodefault): Handle resolving overloaded fns. Use + same_type_p for pmf bits. Don't use build_binary_op to compare + raw pointers to methods. + (convert_for_assignment): Check for OFFSET_REF, not OFFSET_TYPE, + to decide when to call resolve_offset_ref. + (build_c_cast, convert_for_initialization): Likewise. + * cvt.c (build_expr_type_conversion): Likewise. + +1999-05-06 Nathan Sidwell + + * call.c (build_new_method_call): Use TYPE_MAIN_VARIANT of class. + +1999-05-05 Mark Mitchell + + * decl2.c (start_objects): Don't let static constructors and + destructors get inlined. + + * parse.y (nested_name_specifier): Make sure ordinary types are + complete, just like template types. + * parse.c: Regenerated. + + * pt.c (check_explicit_specialization): Improve error messages. + +1999-05-04 Martin von Löwis + + * typeck.c (string_conv_p): Use same_type_p to check whether we + try to convert between char and wchar_t. + +1999-05-03 Mark Mitchell + + * search.c (lookup_field_r): Set the TREE_TYPE of an ambiguous + lookup to error_mark_node here. + (lookup_member): Revise documentation. Add comments. Don't set + the TREE_TYPE to error_mark_node here, and don't build up an extra + TREE_LIST for ambiguous lookups. + (setup_class_bindings): Adjust accordingly. + (push_class_decls): Revise out-of-date comments. + + * typeck.c (build_const_cast): Tighten checks for legality. + +1999-05-02 Martin von Löwis + + * init.c (build_member_call): Lookup names coming from + namespace-scoped LOOKUP_EXPR. + +1999-05-03 Jim Blandy + + * gxxint.texi: Add documentation for 'I'. + +1999-05-02 Martin von Löwis + + * tinfo.cc (operator==): Qualify type_info with std::. + +1999-05-02 Mark Mitchell + + * cp-tree.h (lang_decl_flags): Remove comdat. Updated dummy. + (DECL_COMDAT): Remove definition. + +1999-05-01 Mark Mitchell + + * decl.c (wrapup_globals_for_namespace): Fix thinko in previous + change. + +1999-04-30 Mark Mitchell + + * class.c (build_vtable): Use build_lang_decl when building + vtables, not just build_decl. + (prepare_fresh_vtable): Likewise. + * decl.c (wrapup_globals_for_namespace): Mark vtables as + DECL_EXTERNAL when calling wrapup_global_declarations. + * decl2.c (priority_info_s): Add initializations_p and + destructions_p members. + (finish_vtable_vardecl): Use TREE_SYMBOL_REFERENCED, not TREE_USED, + when deciding what vtables to write out. + (ssdf_decls): New variable. + (ssdf_decls_used): Likewise. + (start_static_storage_duration_function): Deal with being called + multiple times. Avoid inlining this function. + (generate_inits_for_priority): Deal with reuse of priority map. + (get_priority_info): Clear initializations_p and destructions_p. + (do_static_initialization): Tweak comment. + (do_static_destruction): Likewise. Fix condition on sentries for + destruction. + (generate_ctor_or_dtor_function): Call all of the static storage + duration functions. + (generate_ctor_or_dtor_function_for_priority): Check + initializations_p and destructions_p to see what priorities need + initialization functions. + (finish_file): Rework to generate multiple static storage duration + functions, rather than just one. + + * typeck.c (build_const_cast): Tweak last change to handle + templates correctly. + + * typeck.c (build_const_cast): Disallow use of const_cast to + anything but a pointer or reference type. + +1999-04-30 Nathan Sidwell + + * decl.c (cp_finish_decl): Don't permit arrays of abstract or + signature type. + +1999-04-29 Mark Mitchell + + * decl2.c (do_static_destruction): Remove obsolete FIXME comment. + (finish_file): Indent comments properly. + +1999-04-29 Richard Henderson + + * decl2.c (do_static_initialization): Call do_pending_stack_adjust. + (do_static_destruction): Likewise. + +1999-04-29 Nathan Sidwell + + * cp-tree.h (TYPE_NOTHROW_P): New macro. + * decl2.c (delete_sanity): Warn on deleting void *. + * init.c (build_new_1): Use TYPE_NOTHROW_P. + * typeck.c (c_expand_return): cp_pedwarn on returning NULL from + throwing operator new. + +1999-04-28 Nathan Sidwell + + * cp-tree.h (build_component_addr): Remove prototype. + * typeck.c (build_component_addr): Make static. Remove MSG + argument. + (build_component_addr): Remove MSG parameter, clean up + comment. + (build_x_function_call): Use cp_error. + (build_unary_op): Adjust call of build_component_addr. + +1999-04-28 Mark Mitchell + + * pt.c (tsubst_friend_class): Check for NULL. + +Wed Apr 28 11:42:22 1999 Andreas Schwab + + * search.c (binfo_for_vtable): Initialize bfvi.var. + +1999-04-27 Nathan Sidwell + + * rtti.c (build_x_typeid): Check rtti is enabled. + +1999-04-26 Mark Mitchell + + * search.c (is_subobject_of_p): Make sure we're looking at the + right baseclasses. + +1999-04-26 Marc Espie + + * Make-lang.in (cplib2.ready): Don't depend on phony targets. + +1999-04-23 Mark Mitchell + + * decl2.c (finish_file): Tweak handling of extern inlines so that + they are not unnecessarily put out. + + * search.c (is_subobject_of_p): Handle TEMPLATE_TYPE_PARMs and + such as base classes. + +1999-04-22 Brendan Kehoe + + * tree.c (build_exception_variant): Fix typo: use the chain of U, + not trying V, while cycling through U. + +1999-04-22 Mark Mitchell + + * cp-tree.h (lang_decl_flags): Remove returns_first_arg and + preserves_first_arg. Enlarge dummy accordingly. + (DECL_TINFO_FN_P): New macro. + (SET_DECL_TINFO_FN_P): Likeiwse. + (DECL_RETURNS_FIRST_ARG): Remove. + (DECL_PRESERVES_THIS): Likewise. + (DECL_INIT_PRIORITY): New macro. + (finish_struct_1): Change prototype. + (cat_namespace_levels): Remove prototype. + (vtable_decl_p): New prototype. + (vtype_decl_p): Likewise. + (sigtable_decl_p): Likewise. + (walk_globals_pred): New typedef. + (walk_globals_fn): Likewise. + (walk_globals): New prototype. + (walk_namespaces_fn): New typedef. + (walk_namespaces): New prototype. + (wrapup_globals_for_namespace): Likewise. + (walk_vtables): Remove prototype. + (walk_sigtables): Likewise. + (instantiate_pending_templates): New prototype. + * class.c (finish_struct_1): Don't return a value. + * decl.h (pending_statics): Remove declaration. + * decl.c (walk_namespaces_r): New function. + (walk_globals_r): Likewise. + (vtable_decl_p): Likewise. + (vtype_decl_p): Likewise. + (sigtable_decl_p): Likewise. + (walk_namespaces): Likewise. + (walk_globals_data): New type. + (walk_globals): New function. + (wrapup_globals_for_namespace): Likewise. + (expand_static_init): Remove assertion. Remove redundancy in + conditional. Don't put static data members in static_aggregates + Tidy. + (finish_function): Remove redundancy in conditional. Don't set + DECL_RETURNS_FIRST_ARG. + (cat_namespace_levels): Remove. + * decl2.c: Include splay-tree.h and varray.h. + (priority_info_s): New structure. + (finish_vtable_vardecl): Change prototype. Adjust for new calling + conventions. + (prune_vtable_vardecl): Likewise. + (finish_sigtable_vardecl): Likewise. + (setup_initp): Remove. + (do_dtors): Remove. + (do_ctors): Remove. + (start_static_storage_duration_function): New function. + (generate_inits_for_priority): Likewise. + (finish_static_storage_duration_function): Likewise. + (get_priority_info): Likewise. + (do_static_initialization): Likewise. + (do_static_destruction): Likewise. + (do_static_initialization_and_destruction): Likewise. + (generate_ctor_or_dtor_function): Likewise. + (generate_ctor_and_dtor_functions_for_priority): Likewise. + (pending_statics): Make it a varray. + (pending_statics_used): New variable. + (saved_inlines): Make it a varray. + (saved_inlines_used): New variable. + (finish_static_data_member): Change method of updating + pending_statics. + (mark_inline_for_output): Remove #if 0'd code. Change method of + updating saved_inlines. + (walk_vtables): Remove. + (walk_sigtables): Likewise. + (import_export_decl): Use DECL_TINFO_FN_P. + (pending_templates): Remove declaration. + (maybe_templates): Likewise. + (static_aggregates_initp): Likewise. + (setup_initp): Likewise. + (finish_objects): Simplify. + (INITIALIZE_P_IDENTIFIER): New macro. + (PRIORITY_IDENTIFIER): New macro. + (SSDF_IDENTIFIER): New macro. + (initialize_p_decl): New variable. + (priority_decl): Likewise. + (ssdf_decl): Likewise. + (priority_info_map): Likewise. + (finish_file): Recode output of static intializers and other + file-scope finalization tasks. + * error.c (OB_END_TEMPLATE_ID): New macro. + (dump_type_real): Use it. + (dump_decl): Likewise. + (dump_function_name): Likewise. + * lex.c (set_typedecl_interface_info): Adjust for new walk_globals + interface. + (check_newline): Use walk_globals, not walk_vtables. + * pt.c (pending_tempalte_expansions): Remove. + (set_vardecl_interface_info): Likewise. + (pending_templates): Make static. + (maybe_templates): Likewise. + (instantiate_class_template): Adjust call to finish_struct_1. + (instantiate_pending_templates): New function. + * rtti.c (get_tinfo_fn): Use SET_DECL_TINFO_FN_P. + * tree.c (static_aggregates_initp): Remove. + (cp_valid_lang_attribute): Don't use it; use DECL_INIT_PRIORITY + instead. + * Makefile.in (decl2.o): Depend on varray.h and splay-tree.h. + + * gxx.gperf (RETURN): Rename to RETURN_KEYWORD to avoid clashes + with the RTL code RETURN. + * hash.h: Regenerated. + * lex.c (reinit_parse_for_block): Use RETURN_KEYWORD. + * parse.y: Replace RETURN with RETURN_KEYWORD throughout. + * parse.c: Regenerated. + * pt.c: Include varray.h. Include rtl.h since varray.h requires + it. + (inline_parm_levels): New variable. + (inline_parm_levels_used): Likewise. + (maybe_begin_member_template_processing): Update them. + (maybe_end_member_template_processing): Use them, rather than + guessing how many levels to pop. + + * decl.c (make_typename_type): Tighten error-checking. + +1999-04-20 Mark Mitchell + + * cp-tree.h (build_binary_op): Remove unneeded parameter. + * class.c (build_vrable_entry_ref): Adjust call to + build_binary_op. + * decl.c (expand_static_init): Likewise. + (grokdeclarator): Likewise. + (finish_function): Likewise. + * decl2.c (delete_sanity): Likewise. + (do_dtors): Likewise. + (do_ctors): Likewise. + * error.c (dump_type_suffix): Likewise. + * expr.c (cplus_expand_expr): Likewise. + * init.c (resolve_offset_ref): Likewise. + (build_new): Likewise. + (build_new_1): Likewise. + (build_vec_delete_1): Likewise. + (expand_vec_init_catch_clause): Likewise. + (build_delete): Likewise. + * pt.c (tsubst): Likewise. + * rtti.c (synthesize_tinfo_fn): Likewise. + * search.c (expand_upcast_fixups): Likewise. + (expand_direct_vtbls_init): Likewise. + * typeck.c (get_member_function_from_ptrfunc): Likewise. + (build_binary_op_nodefault): Likewise. + (point_int_sum): Likewise. + (pointer_diff): Likewise. + (build_unary_op): Likewise. + (build_modify_expr): Likewise. + (get_delta_difference): Likewise. + (build_ptrmemfunc): Likewise. + (expand_ptrmemfunc_cst): Likewise. + +1999-04-20 Jason Merrill + + * decl.c (grokfndecl): Always call cplus_decl_attributes. + * decl2.c (grokfield): Pass attrlist to grokdeclarator. + +1999-04-19 Mark Mitchell + + * cp-tree.h (finish_static_data_member_decl): New function. + * decl2.c (finish_static_data_member_decl): Split out from ... + (grokfield): Here. + * pt.c (instantiate_class_template): Use it here instead of + trying to fake it. + (tsubst_decl): Don't set DECL_ASSEMBLER_NAME; + finish_static_data_member_decl will do that. Explicit set + DECL_EXTERNAL to match non-template processing. + +1999-04-18 Mark Mitchell + + * cp-tree.h (finish_class_definition): Add parameter. + * parse.y (structsp): Use it. Don't call pop_scope here. + * parse.c: Regenerated. + * semantics.c (finish_class_definition): Pop it here. + +1999-04-17 Mark Mitchell + + * decl.c (xref_tag): Revise handling of nested template + declarations. + * pt.c (check_explicit_specialization): Tweak handling of friend + templates in template classes. + (tsubst_friend_class): Handle friend declarations for nested + member template classes. + +1999-04-16 Mark Mitchell + + * class.c (finish_struct): Remove unused variable. + (pushclass): Likewise. + (invalidate_class_lookup_cache): Likewise. + * cp-tree.def (TYPENAME_TYPE): Improve documentation. + * decl.c (build_typename_type): Make sure TYPENAME_TYPE_FULLNAME + doesn't get obliterated. + (make_typename_type): Handle template classes correctly. + + * cp-tree.h (TREE_NONLOCAL_FLAG): Remove. + (storetags): Declare. + * class.c (finish_struct): Don't use TREE_NONLOCAL_FLAG. + (pushclass): Likewise. Use storetags to install tag declarations, + not pushtag. + (invalidate_class_lookup_cache): Don't use TREE_NONLOCAL_FLAG. + * decl.c (storetags): Make it global. + (push_class_binding): Set INHERITED_VALUE_BINDING_P for an + implicit typename declaration. + (pushtag): Tidy. Don't use TREE_NONLOCAL_FLAG. + * method.c (hack_identifier): Likewise. + * search.c (lookup_member): Likewise. + + * decl.c (warn_about_implicit_typename_lookup): New function. + (lookup_name_real): Use it. Rework handling of implicit typename + extension. + +1999-04-15 Mark Mitchell + + * cp-tree.h (lookup_nested_field): Remove. + * class.c (push_nested_class): Handle UNION_TYPEs. + (pop_nested_class): Likewise. + * decl.c (lookup_name_real): Don't call lookup_nested_field. + (start_decl): Use push_nested_class, not just pushclass. + (cp_finish_decl): Use pop_nested_class, not just popclass. + * search.c (lookup_nested_field): Remove. + + * cp-tree.h (lang_type): Add documentation. + * decl2.c (handle_class_head): Create template declarations here, + as appropriate. + * parse.y (class_head): Return whether or not we entered a new + scope, as well as the type named. + (named_class_head): Likewise. + (named_complex_class_head_sans_basetype): Likewise. + (structsp): Adjust accordingly. Pop scope when required. + * parse.c: Regenerated. + * pt.c (check_default_tmpl_args): Robustify. + (redeclare_class_template): Likewise. + (instantiate_class_template): An instantiation of an + anonymous union is itself an anonymous union. + * semantics.c (begin_class_definition): Don't create template + declarations here. + +1999-04-15 Jason Merrill + + * parse.y (after_type_declarator_intern): New nonterminal. + (after_type_declarator): Use it. + (direct_after_type_declarator): Likewise. Move above + nonnested_type to fix reduce/reduce conflict resolution. + (declmods): Reducing from just 'attributes' has EMPTY precedence. + * Makefile.in (CONFLICTS): Update. + + * decl.c (define_label): Downgrade error for jumping over a + non-POD decl to pedwarn. + +1999-04-14 Mark Mitchell + + * cp-tree.h (popclass): Change declaration. + (pop_nested_class): Likewise. + (poplevel_class): Remove declaration. + * call.c (convert_default_argument): Pass no arguments to + popclass. + * class.c (finish_struct_1): Likewise. + (finish_struct): Likewise. + (popclass): Remove argument. Simplify code accordingly. + (pop_nested_class): Likewise. + * decl.c (poplevel_class): Declare it here, and make it static. + (poplevel): Handle class scopes. + (poplevel_class): Don't take an rgument. Simplify. + (pop_everything): Pass no arguments to pop_nested_class. + (cp_finish_decl): Pass no arguments to popclass. + (grokdeclarator): Pass no arguments to pop_nested_class. + (finish_function): Likewise. + * decl2.c (grokfield): Likewise. + (pop_scope): Pass no arguments to popclass. + * lex.c (do_pending_defargs): Pass no arguments to pop_nested_class. + * pt.c (instantiate_class_template): Move call to pushclass, and + document. Pass no arguments to popclass. + (regenerate_decl_from_template): Likewise. + +1999-04-14 Jason Merrill + + * typeck.c (build_unary_op): Handle taking the address of a unique + bound non-static member function. + +1999-04-13 Martin von Loewis + + * lang-options.h (-Wdeprecated): New flag. + * decl2.c (warn_deprecated): New flag. + (lang_decode_option): Deprecated this-is-variable, + external-templates, alt-external-templates. + Support -Wdeprecated. + * errfn.c (cp_deprecated): New function. + +1999-04-13 Jason Merrill + + * decl2.c (setup_initp): Compare DECL_ASSEMBLER_NAME instead + of the decls themselves. + + * pt.c (tsubst_function_type): Copy attributes over. + + * tree.c (cp_valid_lang_attribute): New fn. Handle init_priority + and com_interface. + * cp-tree.h: Add prototype. + * decl.c (init_decl_processing): Set valid_lang_attribute. + +1999-04-13 Mark Mitchell + + * class.c (finish_struct_1): Look at the const-ness of the field's + type, not the TREE_READONLY-ness of the declaration. + * method.c (synthesize_method): Likewise. + * pt.c (tsubst_decl): Call c_apply_type_quals_to_decl when + creating new declarations. + +1999-04-13 Mike Stump + + * decl2.c (import_export_decl): Because vtables always reference + virtual functions, even if they are inlined, don't allow + -fno-implement-inlines to not emit them, instead, emit them with + the vtable. + * decl.c (start_function): Likewise. + +1999-04-12 Jason Merrill + + * cp-tree.h (struct lang_type): Add com_interface. + (CLASSTYPE_COM_INTERFACE): New macro. + * class.c (set_rtti_entry): COM interface classes have no RTTI + entries in their vtables; adjust. + (add_virtual_function, finish_base_struct, skip_rtti_stuff, + modify_one_vtable, fixup_vtable_deltas1, override_one_vtable, + finish_struct_1): Likewise. + * decl2.c (mark_vtable_entries): Likewise. + * rtti.c (build_headof, get_tinfo_fn_dynamic): Likewise. + * search.c (get_abstract_virtuals_1, get_abstract_virtuals, + expand_upcast_fixups): Likewise. + * tree.c (debug_binfo): Likewise. + + * cp-tree.h (COMPARE_NO_ATTRIBUTES): New macro. + * typeck.c (comptypes): If we get it, ignore attributes. + * class.c (instantiate_type): Use BASELINK_P. Change complain + parameter to flags; 2 means ignore attributes. + * call.c (build_op_delete_call): Pass it. + + * decl.c (xref_tag): Only complain once about using a typedef-name + with 'struct'. Downgrade to pedwarn. + + * decl.c (grokdeclarator): Allow [] syntax for zero-length array. + + * parse.y (absdcl_intern): New nonterminal. + (absdcl, direct_abstract_declarator): Use it. + + * pt.c (lookup_template_class): Look through implict typename. + +1999-04-11 Mark Mitchell + + * friend.c (add_friend): Deal gracefully with error_mark_node. + * method.c (build_overload_value): Handle pointers-to-members as + template parameters. + + * decl.c (push_binding): Fix typo in comment. + +1999-04-10 Mark Mitchell + + * error.c (dump_type_real): If a typename is a template-id, put + out the template arguments. + (dump_expr): Handle TEMPLATE_ID_EXPR. + * pt.c (lookup_template_class): Now that full arguments are + available everywhere, remove code that tried to guess them. + +1999-04-09 Mark Mitchell + + * decl.c (make_typename_type): Complain if we don't find a type + when trying to make a typename type for a non-template type. + +1999-04-09 Jason Merrill + + * decl.c (start_decl): Pass attributes to grokdeclarator. + (grokdeclarator): Handle attributes on constructor-syntax + initializers. + +1999-04-08 Mark Mitchell + + * error.c (dump_expr): Don't crash on INDIRECT_REFs whose operands + don't have types. + + * search.c (template_self_reference_p): Tweak. + +1999-04-07 Mark Mitchell + + * init.c (build_offset_ref): Don't build yet another weird data + structure to describe overloaded functions. + +1999-04-06 Mark Mitchell + + * cp-tree.h (BASELINK_P): New macro. + (SET_BASELINK_P): Likewise. + * init.c (build_member_call): Remove needless assignment in if + statement. + * search.c (lookup_field_r): Fix handling when we are looking + specifically for a type; these are not hidden by functions and + variables. + (lookup_member): Use SET_BASELINK_P. + * tree.c (is_overloaded_fn): Use BASELINK_P. + (really_overloaed_fn): Likewise. + (get_first_fn): Likewise. + +1999-04-05 Mark Mitchell + + * decl.c (lookup_name_current_level): Tweak, and improve + documentation. + + * class.c (maybe_fixup_vptrs): Remove declaration. + (build_class_init_list): Likewise. + * decl.c (pushdecl_class_level): Call check_template_shadow here + ... + (push_class_level_binding): ... not here. + * search.c (dfs_push_type_decls): Only avoid + template-self-reference TYPE_DECLs if they are from base classes. + +1999-04-04 Mark Mitchell + + * pt.c (check_template_shadow): Don't treat OVERLOADs as _DECL + nodes. Tidy. + +1999-04-03 Jason Merrill + + * class.c (maybe_fixup_vptrs, build_class_init_list): Lose. + (finish_struct_1): Don't call build_class_init_list. + +1999-04-02 Mark Mitchell + + * tinfo.h (__class_type_info): Fix illegal declaration. + + * cp-tree.def (TEMPLATE_ID_EXPR): Update comment. + * cp-tree.h (INHERITED_VALUE_BINDING_P): New macro. + (IDENTIFIER_CLASS_VALUE): Improve documentation. + (is_properly_derived_from): Declare. + (invalidate_class_lookup_cache): Likewise. + (maybe_maybe_note_name_used_in_class): Likewise. + (note_name_declared_in_class): Likewise. + (push_using_decl): Remove duplicate declaration. + (id_in_current_class): Remove declaration. + (push_class_binding): Change prototype. + (clear_identitifer_class_values): Declare. + * call.c (is_properly_derived_from): Make it global. + (build_new_function_call): Be careful about updating candidates. + (build_new_method_call): Handle COMPONENT_REFs. Don't crash when + asked to make illegal calls. + * class.c: Include splay-tree.h. + (class_stack_node): Add names_used slot. + (check_member_decl_is_same_in_complete_scope): Remove. + (add_method): Fix comment. Push the declaration into class + scope. + (finish_struct_1): When popping the class, pop the bindings too. + Remove check for data member/function member conflict. + (finish_struct): Remove calls to + check_member_decl_is_same_in_complete_scope. Change calls to + popclass. + (pushclass): Clear names_used in the class stack entry. + Use invalidate_class_lookup_cache to remove cached entries, rather + than magic values with popclass. Clear IDENTIFIER_CLASS_VALUE + before entering a new class. Remove dead code. Don't mess with + current_function_decl when pushing declarations. + (invalidate_class_lookup_cache): New function, split out from ... + (popclass): Here. Clean up names_used on our way out. + (instantiate_type): Adjust. + (build_self_reference): Don't push the declaration here. + (maybe_note_name_used_in_class): New function. + (note_name_declared_in_class): Likewise. + * decl.c (add_binding): Change prototype. + (find_class_binding_level): New function. + (innermost_nonclass_level): Likewise. + (current_binding_level): Update documentation. + (inner_binding_level): Remove. Replace with current_binding_level + throughout. + (push_binding_level): Remove special handling of + class_binding_level. + (pop_binding_level): Likewise. Use find_class_binding_level. + (suspend_binding_level): Likewise. + (global_bindings_p): Use innermost_nonclass_level. + (toplevel_bindings_p): Likewise. + (namespace_bindings_p): Likewise. + (pseudo_global_level_p): Likewise. + (push_binding): Clear INHERITED_VALUE_BINDING_P. + (add_binding): Check for illegal multiple declarations. Return a + value indicating whether or not the new binding was legal. + (push_local_binding): Skip over class binding levels. Check + return value from add_binding. + (push_class_binding): Set INHERITED_VALUE_BINDING_P. Call + note_name_declared_in_class. + (pushlevel_class): Remove "fake out the rest of the compiler" + code. + (poplevel_class): Reset IDENTIFIER_CLASS_VALUEs. + (clear_identifier_class_values): New function. + (pop_from_top_level): Use it. + (pop_everything): Tweak. + (maybe_process_template_type_declaration): Don't push the + declaration for the template here. + (pushtag): Don't push tag declarations into class scope here. + (pushdecl): Apply DeMorgan's law for readability. + (pushdecl_class_level): Remove special-case code for + TYPE_BEING_DEFINED. Handle OVERLOADs and anonymous unions. + (push_class_level_bindng): Deal with inherited bindings. + (lookup_name_real): Remove special-case code for + TYPE_BEING_DEFINED, and some implicit typename magic. + (grokdeclarator): Handle COMPONENT_REF for a template function. + (build_enumerator): Don't call pushdecl_class_level here. + (id_in_current_class): Remove. + * decl2.c (grokfield): Don't call pushdecl_class_level or + check_template_shadow. + * errfn.c (cp_file_of): Don't declare. + (cp_line_of): Likewise. + * error.c (dump_decl): Handle an OVERLOAD. + (cp_file_of): Likewise. + (cp_line_of): Likewise. + * init.c (build_member_call): Handle a COMPONENT_REF. + * lex.c (do_identifier): Call maybe_note_name_used_in_class, not + pushdecl_class_level. + * method.c (hack_identifier): Build COMPONENT_REFs for references + to member templates as well as member functions. Remove dead + code. + * parse.y (left_curly): Remove. + (nonnested_type): Call maybe_note_name_used_in_class, not + pushdecl_class_level. + * parse.c: Regenerated. + (nested_name_specifier_1): Likewise. + * pt.c (check_explicit_specialization): Adjust, for robustness. + (check_template_shadow): Handle OVERLOADs. + (build_template_decl): Set DECL_CONSTRUCTOR_P on the + TEMPLATE_DECL, if appropriate. + * search.c (envelope_add_decl): Remove. + (dfs_pushdecls): Likewise. + (dfs_compress_decls): Likewise. + (dfs_push_decls): New function. + (dfs_push_type_decls): Likewise. + (setup_class_bindings): Likewise. + (template_self_reference_p): Likewise. + (lookup_field_r): Use it. + (looup_member): Remove old comment. Deal with ambiguity. + (push_class_decls): Use dfs_push_decls and dfs_push_type_decls, + and remove envelope processing. + * semantics.c (begin_class_definition): Let pushclass push + declarations for base classes. + (finish_member_declaration): Push declarations into class scope. + * typeck.c (build_component_ref): Just put an OVERLOAD into the + COMPONENT_REF, not a TREE_LIST of an OVERLOAD. + (build_x_function_call): Deal with OVERLOAD. Handle template-ids. + * Makefile.in (class.o): Depend on splay-tree.h. + +Wed Mar 31 11:30:43 1999 Nathan Sidwell + + * cvt.c (convert_pointer_to_real): Use same_type_p. + * typeck.c (comp_target_types): Use same_type_p. + +1999-03-31 Jason Merrill + + * semantics.c (begin_inline_definitions, + finish_inline_definitions): Rename from finish_default_args and + begin_inline_definitions, respectively, to something that isn't a + total lie. :) + * parse.y (structsp): Adjust. + + * tree.c (hash_tree_cons): Remove obsolete via_* parms. + (list_hash_lookup): Likewise. + (hash_tree_chain): Adjust. + * pt.c (tsubst): Adjust. + (tsubst_arg_types): Use plain hash_tree_cons. + * cp-tree.h (hash_tree_cons_simple): Lose. + * parse.y (declmods, nonempty_cv_qualifiers): Use hash_tree_cons. + +Wed Mar 31 10:48:29 1999 Kaveh R. Ghazi + + * Makefile.in (hash.h): Generate using gperf language 'C', not + 'KR-C', so gperf uses the `const' keyword on strings. + + * gxx.gperf (resword): Const-ify a char*. + +1999-03-30 Jason Merrill + + * cp-tree.h (IDENTIFIER_AS_DESC, IDENTIFIER_AS_LIST, + CLASSTYPE_BASELINK_VEC, CLASSTYPE_N_SUPERCLASSES, + CLASSTYPE_N_BASECLASSES, CLASSTYPE_MAX_DEPTH, + CLASSTYPE_BASE_INIT_LIST, CLASSTYPE_AS_LIST, CLASSTYPE_ID_AS_LIST, + CLASSTYPE_BINFO_AS_LIST): Remove cruft. + * class.c, lex.c, parse.y, ptree.c, search.c, semantics.c, + tree.c: Adjust. + +1999-03-29 Jason Merrill + + * decl2.c (lang_decode_option): Remove -Wsign-promo from -Wall. + +1999-03-28 Jason Merrill + + * pt.c (fn_type_unification): Ignore 'this' parm from conversion ops. + +1999-03-27 Mark Mitchell + + * cp-tree.h (add_friend): Declare. + (add_friends): Likewise. + * friend.c (add_friend): Make it global. Don't add to + DECL_BEFRIENDING_CLASSES if the befriending class is a template. + (add_friends): Make it global. + (make_friend_class): Don't add to DECL_BEFRIENDING_CLASSES if the + befriending class is a template. + * parse.y (component_decl_1): Fix typo in comment. + * parse.c: Regenerated. + * pt.c (instantiate_class_template): Use add_friend and + add_friends rather that duplicating some of their functionality + here. + +1999-03-27 Jason Merrill + + * call.c (build_field_call): Unify 'this' and non-'this' cases. + + * typeck.c (build_indirect_ref): Check for 'this' sooner. + +Fri Mar 26 10:20:34 1999 Kaveh R. Ghazi + + * call.c (op_error): Const-ify a char*. + (add_candidate, source_type, add_warning): Add static prototype. + (print_z_candidates): Const-ify a char*. + + * class.c (resolve_address_of_overloaded_function, + fixed_type_or_null, build_vtable_entry_ref): Add static prototype. + (get_vtable_name, finish_struct_1): Const-ify a char*. + + * cvt.c (convert_to_reference): Likewise. + + * decl.c (redeclaration_error_message, record_builtin_type, + record_unknown_type, member_function_or_else, bad_specifiers): + Likewise. + (find_binding, select_decl, unqualified_namespace_lookup, + lookup_flags, qualify_lookup, record_builtin_java_type, tag_name): + Add static prototype. + (warn_extern_redeclared_static, duplicate_decls, pushdecl, + implicitly_declare, record_builtin_java_type, define_function, + grok_op_properties, tag_name): Const-ify a char*. + + * cp-tree.h (FORMAT_VBASE_NAME): Allow parameter `BUF' to be const. + (define_function, finish_builtin_type): Const-ify a char*. + (cp_error, cp_error_at, cp_warning, cp_warning_at, cp_pedwarn, + cp_pedwarn_at, cp_compiler_error, cp_sprintf): Add prototype args. + (file_name_nondirectory): Const-ify a char*. + (init_filename_times): Don't prototype. + (compiler_error): Prototype. + (yyerror, init_repo): Const-ify a char*. + (build_srcloc): Don't prototype. + (build_x_indirect_ref, build_indirect_ref, build_component_addr): + Const-ify a char*. + (warn_for_assignment): Don't prototype. + (convert_for_initialization, readonly_error, check_for_new_type, + GNU_xref_begin, GNU_xref_file, GNU_xref_ref, GNU_xref_call): + Const-ify a char*. + + * decl2.c (acceptable_java_type, output_vtable_inherit, + setup_initp, start_objects, finish_objects, do_dtors, do_ctors, + merge_functions, decl_namespace, validate_nonmember_using_decl, + do_nonmember_using_decl): Add static prototype. + (lang_f_options): Const-ify a char*. + (finish_builtin_type): Likewise. + (add_function, arg_assoc_namespace, arg_assoc_class): Add static + prototype. + + * errfn.c: Include cp-tree.h. + (cp_thing): Add static prototype. + (compiler_error): Don't protoptype. + (cp_compiler_error): Cast `compiler_error' to `errorfn' before + passing it to `cp_thing'. + + * error.c (interesting_scope_p): Add static prototype. + + * except.c (build_eh_type_type, build_eh_type_type_ref): Const-ify + a char*. + + * init.c (compiler_error): Don't prototype. + (member_init_ok_or_else): Const-ify a char*. + (build_java_class_ref): Add static prototype. + + * lex.c (compiler_error): Don't prototype. + (get_time_identifier, interface_strcmp, extend_token_buffer, + handle_cp_pragma): Const-ify a char*. + (is_global, init_filename_times): Add static prototype. + (file_name_nondirectory, cplus_tree_code_name): Const-ify a char*. + (compiler_error): Change from fixed args to variable args. + (yyerror): Const-ify a char*. + + * parse.y (cond_stmt_keyword): Const-ify a char*. + (parse_decl): Add static prototype. + + * pt.c (template_args_equal, print_template_context): Likewise. + (print_candidates, check_default_tmpl_args): Const-ify a char*. + (instantiate_class_template): Likewise. + + * repo.c (get_base_filename, open_repo_file, init_repo): Likewise. + + * rtti.c (call_void_fn, expand_generic_desc, expand_si_desc, + expand_class_desc, expand_ptr_desc, expand_attr_desc): Likewise. + + * search.c (lookup_field_info, lookup_member): Likewise. + (lookup_member): Cast the first argument of `bzero' to a PTR. + + * sig.c (compiler_error): Don't prototype. + (build_signature_pointer_or_reference_nam): Const-ify a char*. + (get_sigtable_name, build_member_function_pointer): Likewise. + + * tree.c (compiler_error): Don't prototype. + (no_linkage_helper, build_srcloc): Add static prototype. + (build_vbase_pointer_fields): Const-ify a char*. + (__eprintf): Don't unnecessarily handle `const' when !__STDC__. + + * typeck.c (compiler_error): Don't prototype. + (convert_for_assignment): Const-ify a char*. + (comp_cv_target_types): Add static prototype. + (build_x_indirect_ref, build_indirect_ref, convert_arguments, + build_component_addr, build_unary_op, convert_for_initialization): + Const-ify a char*. + + * typeck2.c (ack): Add static prototype and change from fixed args + to variable args. + (readonly_error, check_for_new_type): Const-ify a char*. + + * xref.c (_XREF_FILE, find_file, filename, fctname, declname, + fixname, open_xref_file, classname, GNU_xref_begin): Likewise. + (GNU_xref_file): Likewise. Also use `xmalloc' instead of `malloc'. + (GNU_xref_end_scope, GNU_xref_ref, GNU_xref_decl, GNU_xref_call, + gen_assign, GNU_xref_member): Const-ify a char*. + +1999-03-25 Martin von Löwis + + * gxxint.texi: Remove old discussion on copying virtual bases. + +1999-03-25 Zack Weinberg + + * Make-lang.in: Remove all references to g++.o/g++.c. + Link g++ from gcc.o. + +1999-03-25 Jason Merrill + + * decl2.c (comdat_linkage): Treat vtables like functions. + +1999-03-25 Mark Mitchell + + * pt.c (tsubst_decl): tsubst into DECL_BEFRIENDING_CLASSES. + +1999-03-25 Nathan Sidwell + + * decl.c (init_decl_processing): Add `signed' type as a synonym + for `int'. + +1999-03-25 Jason Merrill + + * typeck.c (common_type): Handle cv-qual unification for pointers + to members. + + * decl.c (unqualified_namespace_lookup): Return error_mark_node + on error. + (lookup_name_real): Set LOOKUP_COMPLAIN when *not* parsing. + * lex.c (do_identifier): If we got error_mark_node, call + lookup_name again. + +1999-03-24 Martin von Löwis + + * class.c (finish_struct_1): Always reset TYPE_FIELDS for empty + classes. + +1999-03-24 Jason Merrill + + * decl.c (lookup_name_real): Do nested field lookup regardless of + TYPE_BEING_DEFINED. + +1999-03-24 Mark Mitchell + + * cp-tree.h (lang_type): Remove has_assignment and + has_real_assignment. Add befriending_classes. + (TYPE_HAS_ASSIGNMENT): Remove. + (TYPE_HAS_REAL_ASSIGNMENT): Likewise. + (CLASSTYPE_BEFRIENDING_CLASSES): New macro. + (lang_decl): Document. + (DECL_BEFRIENDING_CLASSES): New macro. + (FRIEND_NAME): Move declaration to more obvious location. + (FRIEND_DECLS): Likewise. + * class.c (finish_struct_1): Don't use TYPE_HAS_REAL_ASSIGNMENT. + * decl.c (duplicate_decls): Copy DECL_BEFRIENDING_CLASSES. + (fixup_anonymous_union): Don't use TYPE_HAS_ASSIGNMENT. + (grok_op_properties): Likewise. + * friend.c (is_friend): Use FRIEND_NAME and FRIEND_DECLS. + (add_friend): Likewise. Don't do weird things with assignment + operators. Update DECL_BEFRIENDING_CLASSES. + (add_friends): Don't do weird things with assignment operators. + (make_friend_class): Likewise. Update + CLASSTYPE_BEFRIENDING_CLASSES. + * pt.c (instantiate_class_template): Don't set + TYPE_HAS_ASSIGNMENT. + (tsubst_copy): Substitute the TREE_TYPE for more unary + expressions. + * ptree.c (print_lang_type): Don't look at TYPE_HAS_ASSIGNMENT. + * search.c (protected_accessible_p): New function. + (friend_accessible_p): Likewise. + (accessible_p): Use them. + +1999-03-23 Mark Mitchell + + * pt.c (convert_nontype_argument): Don't create things that aren't + PTRMEM_CSTs when applying a qualification conversion to a + PTRMEM_CST. + +1999-03-23 Mark Mitchell + + * Makefile.in (OBJS): Don't mention hash.o. + (OBJDEPS): Likewise. + +1999-03-23 Jason Merrill + + * decl2.c (finish_file): Set at_eof to 2 after expanding ctors. + * decl.c (expand_static_init): Make sure we don't add any after + then. + + * decl.c (cp_finish_decl): Move intelligence about handling + DECL_COMDAT for variables from here... + * decl2.c (comdat_linkage): ...to here. + (maybe_make_one_only): Tweak. + (import_export_decl): Call comdat_linkage for variables, too. + (finish_file): Handle template statics properly. + +1999-03-22 Mark Mitchell + + * cp-tree.h (TYPE_PTRMEMFUNC_P): Use TYPE_PTRMEMFUNC_FLAG. + Document internals of pointer-to-member-functions. + (DELTA2_FROM_PTRMEMFUNC): Make it call delta2_from_ptrmemfunc. + (PFN_FROM_PTRMEMFUNC): Likewise. + (build_type_conversion): Remove unused parameter. + (build_ptrmemfunc1): Declare. + (expand_ptrmemfunc_cst): New function. + (delta2_from_ptrmemfunc): Likewise. + (pfn_from_ptrmemfunc): Likewise. + * cvt.c (cp_convert_to_pointer): Remove unused parameter to + build_type_conversion. Use TYPE_PTRMEM_P for readability. + (convert_to_reference): Remove unused parameter to + build_type_conversion. + (ocp_convert): Likewise. + (build_user_type_conversion): Likewise. + * error.c (dump_expr): Handle NULL pointer-to-member functions. + * expr.c (cplus_expand_expr): Handle PTRMEM_CSTs for functions. + * method.c (build_overload_value): Don't go splitting CONSTRUCTORs + open when handling pointer-to-member functions. + * pt.c (convert_nontype_argument): Clean up error messages. Be + more stringent with pointers-to-members. + * typeck.c (build_ptrmemfunc1): Don't declare. Make it global. + (build_unary_op): Tidy ever-so-slightly. + (build_conditional_expr): Remove extra parameter to + build_type_conversion. + (build_ptrmemfunc): Build PTRMEM_CSTs if we know what function + we're using. + (expand_ptrmemfunc_cst): Define. + (delta2_from_ptrmemfunc): Likewise. + (pfn_from_ptrmemfunc): Likewise. + +1999-03-19 Mark Mitchell + + * init.c (build_member_call): Handle template-id expressions + correctly. + * typeck.c (build_x_function_call): Likewise. + +1999-03-19 Chip Salzenberg + + * friend.c (make_friend_class): Avoid core dump when + not-yet-defined friend type lacks TYPE_LANG_SPECIFIC(). + +1999-03-18 Jason Merrill + + * decl.c (start_function): Suppress normal linkage heuristics + for #pragma interface under MULTIPLE_SYMBOL_SPACES. + +1999-03-19 Alexandre Oliva + + * Make-lang.in: ($(INTL_TARGETS)): Depend on cp/parse.c. + ($(srcdir)/cp/parse.c): Moved from ../Makefile.in. + +1999-03-17 Martin von Löwis + + * parse.y (named_complex_class_head_sans_basetype): + Do not push a scope for error_mark_node. + (maybe_base_class_list): Likewise. + + * decl.c (start_decl): Check for error_mark_node as a type. + Detected by g++.brendan/array-refs.C. + (start_decl_1): Likewise. Detected by g++.bugs/900322_01.C. + (maybe_build_cleanup_1): Likewise. Detected by + g++.jason/incomplete1.C. + + * tree.c (build_dummy_object): Use void_zero_node instead of the + error_mark_node. + (is_dummy_object): Check for such a node. + Detected by g++.bob/inherit1.C + +1999-03-16 Jason Merrill + + * method.c (old_backref_index): Split out... + (flush_repeats): From here. Rename back from try_old_backref. + (build_mangled_name): Put back some old-style repeat handling. + +Mon Mar 15 21:57:16 1999 Kaveh R. Ghazi + + * lex.c: Don't include setjmp.h. + (parse_float): New static function. + (pf_args): New struct. + (real_yylex): Use them in call to `do_float_handler'. + +1999-03-15 Mark Mitchell + + * decl.c (xref_basetypes): Set CLASSTYPE_VBASECLASSES here. + * tree.c (layout_basetypes): Not here. + * search.c (dfs_search): Remove; no longer used. + +1999-03-12 Mark Mitchell + + * decl2.c (validate_nonmember_using_decl): Issue sensible + error-messages on bogus qualifiers. + +1999-03-14 Jason Merrill + + * call.c (add_function_candidate): Fix uninitialized variable. + + * Makefile.in (search.o): Add dependency on varray.h. + +1999-03-13 Jason Merrill + + * decl.c (duplicate_decls): Use same_type_p. + * method.c (try_old_backref): Renamed from flush_repeats. Use + same_type_p. Don't try to handle repeats. Return success. + (is_back_referenceable_type): Return 0 if TYPE_FOR_JAVA. Support + calls from old-style code, too. + (check_ktype): Use same_type_p. + (check_btype): Use same_type_p. Don't pull out TYPE_MAIN_VARIANT. + (build_qualified_name): Simplify logic. + (process_overload_item): Strip typedefs and quals at the top. + (build_mangled_name_for_type_with_Gcode): Remove call to + type_canonical_variant. + (build_mangled_name): Likewise. Remove support for old-style + repeats, which have been disabled since 2.7.2. Don't mess with + TREE_USED. + (build_decl_overload_real): Don't mess with TREE_USED. + +1999-03-13 Nathan Sidwell + + * error.c (cp_printers): Add 'F' escape character. + (dump_type_real): Remove TREE_LIST (fnargs) printing. + Functionality moved to dump_parameters. + (dump_type_suffix): Use dump_parameters and dump_exception_spec. + (dump_function_decl): Extend meaning of V parameter. Use + dump_parameters and dump_exception_spec. + (dump_parameters): New static function. + (dump_exception_spec): New static function. + (fndecl_as_string): Change argument semantics. Use + dump_function_decl directly. + + * sig.c (build_signature_table_constructor): Use cp_error. + +1999-03-13 Martin von Löwis + + * semantics.c (finish_switch_cond): Handle error cases gracefully. + Detected by g++.law/enum5.C. + + * typeck.c (build_modify_expr): Check for errors after resolving + offsets. Detected by g++.brendan/static1.C. + + * decl.c (complete_array_type): Ignore initial_value if it is an + error. Detected by g++.benjamin/17930.C. + + * typeck2.c (process_init_constructor): Return error if one argument + is in error. Detected by g++.benjamin/13478.C. + +1999-03-12 Martin von Löwis + + * decl.c (select_decl): Allow class templates when we need types. + * decl2.c (ambiguous_decl): Likewise. + +1999-03-12 Mark Mitchell + + * lex.c (do_identifier): Correct call to enforce_access. + * search.c (accessible_p): Tweak comment. + +1999-03-10 Mark Mitchell + + * semantics.c (begin_class_definition): Call build_self_reference. + (finish_member_declaration): Set DECL_CONTEXT for TYPE_DECLs. + + * search.c (assert_canonical_unmarked): Fix typo in prototype. + + * search.c (dfs_canonical_queue): New function. + (dfs_assert_unmarked_p): Likewise. + (assert_canonical_unmarked): Likewise. + (access_in_type): Use it. + (accessible_p): Likewise. Walk the whole tree when umarking. + + * sig.c (build_signature_table_constructor): Use accessible_p + instead of compute_access. + +1999-03-09 Jason Merrill + + * call.c (add_builtin_candidates): Handle overloaded conversion ops. + +1999-03-09 Mark Mitchell + + * cp-tree.h (flag_access_control): Declare. + (TREE_VIA_PPUBLIC): Document. + (DECL_NONSTATIC_MEMBER_P): New macro. + (enforce_access): Return an indication of whether or not access + was permitted. + (build_self_reference): Change prototype. + (compute_access): Replace with ... + (accessible_p): New function. + (dfs_walk): Change prototype. + (dfs_unmark): Likewise. + (markedp): Likewise. + * call.c (enforce_access): Use accessible_p. + * class.c (build_self_reference): Insert the declaration into the + list of members for this type, and make it public. + * decl.c (xref_basetypes): Avoid ill-timed recursion. + * init.c (build_offset_ref): Use lookup_member, not three separate + name-lookups. Call enforce_access rather than checking for + illegal accesses here. + (resolve_offset_ref): Likewise. + * lex.c (do_identifier): Likewise. + * method.c (hack_identifier): Likewise. + * parse.y (self_reference): Remove. + (opt_component_decl_list): Don't use it. + * parse.c: Regenerated. + * pt.c (print_candidates): Generalize to handle lists of + overloaded functions. + (instantiate_class_template): Don't rely on TREE_VIA_PRIVATE; it's + not set. + (get_template_base): Use new calling convention for dfs_walk. + * search.c: Include varray.h. Add prototypes. + (dfs_walk): Accept a data pointer to pass to the work functions. + All callers changed. All work functions changed. + (breadth_first_search): Rename to bfs_walk, and make consistent + with dfs_walk. + (dfs_walk_real): New function. + (canonical_binfo): New function. + (context_for_name_lookup): Likewise. + (shared_marked_p): Likewise. + (shared_unmarked_p): Likewise. + (lokup_field_queue_p): Likewise. + (lookup_field_r): Generalize to handle both functions and fields. + (lookup_field): Just call lookup_member. + (lookup_fnfields): Likewise. + (lookup_member): Move body of lookup_field here and generalize. + (dfs_accessible_queue_p): Likewise. + (dfs_accessible_p): Likewise. + (dfs_access_in_type): Likewise. + (access_in_type): Likewise. + (compute_access): Remove, and replace with ... + (accessible_p): New function. + (vbase_types): Remove. + (vbase_decl_ptr_intermediate): Likewise. + (vbase_decl_ptr): Likewise. + (vbase_init_result): Likewise. + (closed_envelopes): Likewise. + (bvtable): Likewise. + +1999-03-09 Jason Merrill + + * call.c (add_function_candidate): Check for proper number of args + before checking the validity of those args. + +1999-03-06 Jason Merrill + + * cp-tree.h (struct lang_type): Add anon_union field. + (ANON_UNION_TYPE_P): Use it instead of examining type. + (SET_ANON_UNION_TYPE_P): New macro. + * decl.c (check_tag_decl): Use it. + + * search.c (compute_access): Handle non-type contexts earlier, and + handle NULL_TREE. + + * tree.c (build_exception_variant): Use copy_to_permanent. + + * decl2.c (setup_initp): Give statics with no priority the default + priority here. + (do_dtors, do_ctors, finish_file): Remove special handling of + non-prioritized statics. + +1999-03-05 Mark Mitchell + + * cp-tree.h (ANON_UNION_TYPE_P): Robustify. + * decl.c (make_typename_type): Don't issue an error if an + immediate lookup fails; it migt be resolved later. + * friend.c (is_friend): Add comment. + * search.c (breadth_first_search): Add POSTFN and DATA + parameters. Tidy. All callers changed. + (lookup_field_queue_p): New function. + (lookup_field_r): Likewise. + (lookup_field_post): Likewise. + (lookup_field): Use them, via breadth_first_search, instead of + duplicating logic. + (compute_access): Robustify. + (lookup_fnfield_info): New structure. + +1999-03-05 Jason Merrill + + * pt.c (tsubst, case ARRAY_REF): Use tsubst_expr again. + +1999-03-03 Jason Merrill + + * class.c, decl2.c, method.c, pt.c: Add 'static' to make SunOS 4 + cc happy. + + * decl2.c (import_export_class): Also return if + CLASSTYPE_INTERFACE_ONLY is set. + +1999-03-03 Martin von Löwis + + * decl.c (push_overloaded_decl): Only overwrite the old binding if + there was one. + * decl2.c (do_local_using_decl): Fix loop termination. + +1999-03-02 Mark Mitchell + + * cp-tree.h (determine_specialization): Don't declare. + * pt.c (determine_specialization): Make it static. Eliminate + complain parameter. Note that decl is always non-NULL now, and + simplify accordingly. + + * decl.c (maybe_push_to_top_level): Always call + push_cp_function_context. + (pop_from_top_level): Always call pop_cp_function_context. + +1999-02-26 Nathan Sidwell + + * typeck.c (complete_type_or_else): Add VALUE arg, for helpful + diagnostics. + * cp-tree.h (complete_type_or_else): Added VALUE parameter. + * init.c (build_new_1): Extra arg to complete_type_or_else. + (build_delete): Likewise. + * typeck.c (require_complete_type): Likewise. + (pointer_int_sum): Likewise. + (pointer_diff): Likewise. + (build_component_ref): Likewise. + + * typeck2.c (incomplete_type_error): Always use cp_error. + Show declaration of undefined type, if appropriate. + Deal with UNKNOWN_TYPE nodes. + + * typeck.c (require_complete_type): Use TYPE_SIZE as + size_zero_node to mean incomplete type. + (require_complete_type_in_void): New function. + (build_compound_expr): Call complete_type_in_void for LHS. + (build_c_cast): Call complete_type_in_void for void cast. + * cvt.c (ocp_convert): Call complete_type_in_void for void cast. + * decl.c (cplus_expand_expr_stmt): Void expression checks moved to + require_complete_type_in_void. Call it. + * cp-tree.h (require_complete_type_in_void): Prototype new function. + + * typeck.c (convert_arguments): Use alternative format for + function decls. Don't require_complete_type here. Simplify + diagnostic printing. + (convert_for_initialization): Don't require_complete_type on RHS yet. + * call.c (convert_arg_to_ellipsis): Call require_complete_type. + + * call.c (build_over_call): Cope with qualified void return type. + * semantics.c (finish_call_expr): Likewise. + * typeck.c (build_function_call_real): Likewise. + (c_expand_return): Likewise. + * decl2.c (reparse_absdcl_as_expr): Cope with qualified void type. + + * call.c (print_z_candidates): Use alternate print format, to be + consistent with (pt.c) print_candidates. + * method.c (hack_identifier): List candidate members. + * search.c (lookup_field): Build ambiguous list, and show it, if + ambiguous. + +1999-02-26 Mark Mitchell + + * typeck.c (decay_conversion): Don't confuse constant array + variables with their initializers. + + * decl.c (duplicate_decls): Copy DECL_TEMPLATE_INSTANTIATED when + merging decls. + * pt.c (regenerate_decl_from_template): Tweak for clarity. + (instantiate_decl): Mark a decl instantiated before regenerating + it to avoid recursion. + * tree.c (mapcar): Don't call decl_constant_value unless we know + something is TREE_READONLY_DECL_P. + + * class.c (check_for_override): Don't stop checking when we find + the first overridden function. Delete #if 0'd code. + * search.c (get_matching_virtual): Likewise. + +1999-02-25 Richard Henderson + + * lang-specs.h: Define __FAST_MATH__ when appropriate. + +1999-02-24 Mike Stump + + * typeck.c (convert_for_assignment): Allow boolean integral constant + expressions to convert to null pointer. + +1999-02-24 Martin von Loewis + + * decl.c (lookup_namespace_name): Resolve namespace aliases. + + * class.c (push_nested_class): Allow namespaces. + + * decl2.c (set_decl_namespace): Add friendp parameter. + * decl.c (grokfndecl): Pass it. + (grokvardecl): Likewise. + * cp-tree.h: Change declaration. + +1999-02-24 Jason Merrill + + * pt.c (tsubst): Allow an array of explicit size zero. + +1999-02-23 Jason Merrill + + * errfn.c: Change varargs code to look like toplev.c. + + * method.c (process_modifiers): Don't prepend 'U' for char or + wchar_t. + +1999-02-20 Craig Burley + + * Make-lang.in (cplib2.ready): Don't consider updating + cplib2 stuff if the current directory isn't writable, as + it won't work (such as during a `make install'). + +Sun Feb 21 20:38:00 1999 H.J. Lu (hjl@gnu.org) + + * decl2.c (start_objects): Make file scope constructors and + destructors local to the file if ASM_OUTPUT_CONSTRUCTOR and + ASM_OUTPUT_DESTRUCTOR are defined. + +1999-02-19 Mark Mitchell + + * cp-tree.h (CLASSTYPE_METHOD_VEC): Adjust comment. + (fn_type_unification): Adjust prototype. + (lookup_fnfields_1): Declare. + * call.c (add_template_candidate_real): Adjust call to + fn_type_unification. + * class.c (add_method): Don't allow duplicate declarations of + constructors or destructors. + (resolve_address_of_overloaded_function): Remove unused variable. + Adjust call to fn_type_unification. + * decl.c (grokfndecl): Be more robust in the face of illegal + specializations. + * decl2.c (check_classfn): Remove hokey handling of member + templates. + * pt.c (determine_specialization): Improve comments. Adjust to + handle template argument deduction as per the standard. + (check_explicit_specialization): Fix comment spacing. Handle + type-conversion operators correctly. Improve error-recovery. + (fn_type_unification): Remove EXTRA_FN_ARG parameter. + (get_bindings_real): Simplify handling of static members. + * search.c (lookup_fnfields_1): Make it have external linkage. + * typeck.c (compparms): Fix comment. + (build_unary_op): Don't try to figure out which template + specialization is being referred to when when the address-of + operator is used with a template function. + +Thu Feb 18 23:40:01 1999 Kaveh R. Ghazi + + * cp-tree.h (lvalue_or_else): Qualify a char* with the `const' + keyword to match an analogous change at the top level. + + * tree.c (lvalue_or_else): Likewise. + +1999-02-17 Mark Mitchell + + * decl.c (xref_basetypes): Comment. + * pt.c (instantiate_class_template): Use xref_basetypes. + +1999-02-16 Mark Mitchell + + * cp-tree.h (tsubst): Change prototype. + (tsubst_expr): Likewise. + (tsubst_copy): Likewise. + (type_unification): Remove prototype. + * call.c (convert_default_arg): Adjust call to tsubst_expr. + * class.c (resolve_address_of_overloaded_function): Just use + fn_type_unification. + * decl.c (grokdeclarator): Adjust call to tsubst. + * method.c (build_template_parm_names): Likewise. + * pt.c (GTB_VIA_VIRTUAL): New macro. + (GTB_IGNORE_TYPE): Likewise. + (resolve_overloaded_unification): Add `complain' parameter. + (try_one_overload): Likewise. + (tsubst_template_arg_vector): Likewise. + (tsubst_template_parms): Likewise. + (tsubst_aggr_type): Likewise. + (tsubst_arg_types): Likewise. + (tsubst_call_declarator_parms): Likewise. + (unify): Remove explicit_mask. + (type_unification_real): Likewise. + (get_template_base_recursive): Likewise. + (coerce_template_template_parms): Provide prototype. + (tsubst_function_type): Likewise. + (try_class_unification): New function. + All callers changed to use new complain parameter. + (get_template_base): Use try_class_unification. + (unify): Adjust handling of classes derived from template types. + (fn_type_unification): Substitute explicit arguments before + unification. + +1999-02-16 Kriang Lerdsuwanakij + + * decl.c (pushdecl): Remove dead code. + +1999-02-16 Jason Merrill + + * decl2.c (finish_objects): Fix code I missed in previous change. + +1999-02-13 Jason Merrill + + * decl.c (grokfndecl): Return NULL_TREE instead of error_mark_node. + (grokdeclarator): Don't expect error_mark_node from grokfndecl. + + * pt.c (maybe_process_partial_specialization): Complain about + 'template <>' on non-specialization. + +1999-02-10 Jason Merrill + + * decl.c (grokdeclarator): Catch wierd declarators. + * decl2.c (finish_file): Don't abort because of namespace parsing + failure. + (check_decl_namespace): Remove. + +1999-02-09 Mark Mitchell + + * cp-tree.h (get_template_base): Don't declare. + (dfs_walk): Declare. + (dfs_unmark): Likewise. + (markedp): Likewise. + * pt.c (unify): Remove duplicate declaration. Pass tparms and + targs to get_template_base. + (get_template_base_recursive): Move here from search.c. Check to + see that the base found can be instantiated to form the desired + type. + (get_template_base): Likewise. + (get_class_bindings): Simplify. + * search.c (get_template_base_recursive): Move to pt.c. + (get_template_base): Likewise. + (markedp): Make it global. + (dfs_walk): Likewise. + (dfs_unmark): Likewise. + +1999-02-07 Jason Merrill + + * pt.c (maybe_process_partial_specialization): Complain about + specialization in wrong namespace. + * tree.c (decl_namespace_context): New fn. + +1999-02-06 Kriang Lerdsuwanakij + + * decl2.c (arg_assoc_type): Handle TEMPLATE_TEMPLATE_PARM. + * pt.c (coerce_template_template_parms): Handle nested + template template parameters. + +Sat Feb 6 18:08:40 1999 Jeffrey A Law (law@cygnus.com) + + * typeck2.c: Update email addresses. + +1999-02-04 Kriang Lerdsuwanakij + + * pt.c (unify): Call coerce_template_parms with the COMPLAIN flag + turned off. + +1999-02-04 Jason Merrill + + * lex.c (retrofit_lang_decl): Split out... + (build_lang_decl): From here. + * decl.c (pushdecl): Call it for functions generated by the middle + end that don't have DECL_LANG_SPECIFIC. + * cp-tree.h: Declare it. + + * decl2.c: Remove flag_init_priority. Always enable initp stuff. + (start_objects, finish_objects): Only use special + init_priority code if the user specified a priority. + (do_ctors, do_dtors): Use DEFAULT_INIT_PRIORITY for the non-initp + objects. + +Wed Feb 3 22:50:17 1999 Marc Espie + + * Make-lang.in (GXX_OBJS): Remove choose-temp.o, pexecute.o and + mkstemp.o. Get them from libiberty now. + (DEMANGLER_PROG): Simlarly, remove getopt.o getopt1.o. + +Tue Feb 2 22:38:48 1999 Theodore Papadopoulo + + * decl2.c (lang_decode_option): Use read_integral_parameter. + +1999-02-01 Mark Mitchell + + * pt.c (tsubst, case TYPENAME_TYPE): Check TYPE_BEING_DEFINED + before calling complete_type_or_else. + +Mon Feb 1 09:49:52 1999 Kaveh R. Ghazi + + * input.c (inline): Don't define, its handled by system.h. + +Sun Jan 31 20:34:29 1999 Zack Weinberg + + * decl2.c: Don't define flag_no_ident here. Don't process + -f(no-)ident here. + * cp-tree.h: Don't declare flag_no_ident here. + * lang-specs.h: Map -Qn to -fno-ident. + +1999-01-28 Jason Merrill + + * cp-tree.h (struct tree_binding): Replace scope field with a union. + (BINDING_SCOPE): Adjust. + * decl.c (BINDING_LEVEL): Adjust. + +1999-01-26 Jason Merrill + + * pt.c (instantiate_class_template): Set up the DECL_INITIAL of + member constants. + + * init.c (expand_member_init): Pull out TYPE_MAIN_VARIANT in + a ctor initializer. + + * tree.c (equal_functions): Fix name in prototype. + + * decl.c (push_local_binding): Add FLAGS argument. + (pushdecl, push_overloaded_decl): Pass it. + * decl2.c (do_local_using_decl): Likewise. + * cp-tree.h: Adjust prototype. + * decl.c (poplevel): Fix logic. + + * decl.c (push_local_binding): Also wrap used decls in a TREE_LIST. + (poplevel): Handle that. Fix logic for removing TREE_LISTs. + (cat_namespace_levels): Don't loop forever. + +1999-01-25 Richard Henderson + + * typeck.c (build_reinterpret_cast): Fix typo in duplicated test. + +1999-01-25 Jason Merrill + + * class.c (resolve_address_of_overloaded_function): Mark the + chosen function used. + + * call.c (build_call): Make sure that a function coming in has + been marked used already. + * decl.c (expand_static_init): Call mark_used instead of + assemble_external. + * except.c (call_eh_info, do_pop_exception, expand_end_eh_spec, + alloc_eh_object, expand_throw): Likewise. + * init.c (build_builtin_delete_call): Likewise. + * rtti.c (call_void_fn, get_tinfo_fn, build_dynamic_cast_1, + expand_si_desc, expand_class_desc, expand_ptr_desc, expand_attr_desc, + expand_generic_desc): Likewise. + +1999-01-25 Martin von Löwis + + * tree.c (equal_functions): New function. + (ovl_member): Call it. + +1999-01-24 Jason Merrill + + * cvt.c (cp_convert_to_pointer): Fix conversion of 0 to pmf. + +1999-01-25 Martin von Loewis + + * decl.c (decls_match): Return 1 if old and new are identical. + (push_overloaded_decl): Set OVL_USED when PUSH_USING. + +1999-01-24 Jason Merrill + + * decl.c (start_function): Make member functions one_only on windows. + * decl2.c (import_export_decl): Likewise. + + * decl.c (grokdeclarator): Don't complain about implicit int in + a system header. Change same-name field check to not complain in + a system header instead of within extern "C". + +1999-01-21 Mark Mitchell + + * cp-tree.h (PUSH_GLOBAL): New macro. + (PUSH_LOCAL): Likewise. + (PUSH_USING): Likewise. + (namespace_bindings_p): Declare. + (push_overloaded_decl): Likewise. + * decl.c (push_overloaded_decl): Don't make it static. Check for + illegal declarations after using declarations here. + (namespace_bindings_p): Likewise. + (duplicate_decls): Don't consider declarations from different + namespaces to be the same. + (pushdecl): Use symbolic PUSH_ constants in calls to + push_overloaded_decl. + (push_overloaded_decl_1): Likewise. + * decl2.c (validate_nonmember_using_decl): Tweak `std' handling. + (do_nonmember_using_decl): Check for illegal using declarations + after ordinary declarations here. + (do_local_using_decl): Call pushdecl to insert declarations. + +1999-01-21 Jason Merrill + + * decl.c (grokdeclarator): Fix lang_c -> lang_name_c typo. + +1999-01-21 Mark Mitchell + + * tree.c (build_cplus_array_type_1): Don't call build_array_type + for types involving template parameters. + + * cp-tree.h (PARM_DECL_EXPR): Delete. + (convert_default_arg): Change prototype. + (check_default_argument): Declare. + (search_tree): Likewise. + * call.c (convert_default_arg): Take the function to which the + default argument belongs as a parameter, and do any necessary + instantiation here, instead of ... + (build_over_call): Here. + * decl.c (local_variable_p): New function. + (check_default_argument): Likewise, split out and tidied from ... + (grokparms): Here. + * error.c (dump_expr): Don't set PARM_DECL_EXPR. + * pt.c (tsubst_call_declarator_parms): New function. + (for_each_template_parm): Handle ARRAY_REFs. Do the obvious thing + with CALL_EXPRs, rather than trying to be clever. + (tsubst): Use tsubst_call_declarator_parms. + * tree.c (search_tree): Don't make it static. + * typeck.c (convert_arguments): Use new interface to + convert_default_arg. + +1999-01-20 Mark Mitchell + + * error.c (dump_function_decl): Don't print the argument types for + a function when the verbosity level is negative. + + * call.c (build_over_call): Check format attributes at call-time. + + * pt.c (tsubst_copy): Fix comment. + (unify): Don't allow unification with variable-sized arrays. + + * semantics.c (finish_stmt_expr): When processing a template make + the BIND_EXPR long-lived. + +1999-01-19 Jason Merrill + + * decl2.c (finish_vtable_vardecl): Make vtables comdat here. + (import_export_vtable): Not here. + +1999-01-18 Jason Merrill + + * typeck.c (build_component_ref): Wrap an OVERLOAD around a unique + non-static member function. + +1999-01-18 Nathan Sidwell + + * class.c (instantiate_type): Only diagnose illegal address of member + function if complaining. + + * decl.c (lookup_name_real): Remove duplicate code. + +1999-01-18 Jason Merrill + + * tree.c (copy_template_template_parm): Use permanent_obstack. + +1999-01-18 Kriang Lerdsuwanakij + + * pt.c (unify): Remove restrictions on deduction of argument + of template template parameters. + +1999-01-18 Nathan Sidwell + + * rtti.c (build_dynamic_cast_1): Resolve OFFSET_REF exprs. + + * class.c (resolve_address_of_overloaded_function): Show list of + all candidates, when none of them match. + +1999-01-18 Chip Salzenberg + + * typeck.c (comp_ptr_ttypes_reinterpret): Per ANSI, tighten up + definition of 'casting away const' in reinterpret_cast<>. + +1999-01-18 Graham + + * cvt.c: Add include for decl.h, remove extern for + static_aggregates which is now provided by decl.h. + + * Makefile.in (cvt.o): Add dependency for decl.h and missing + dependencies for convert.h and flags.h. + +1999-01-18 Nathan Sidwell + + * decl2.c (do_dtors): Set current location to that of the + decl, for sensible diagnostics and debugging. + (check_classfn): Issue `incomplete type' error, if + class is not defined. + +1999-01-16 Jason Merrill + + * cp-tree.h: Add prototype for bound_pmf_p. + +1999-01-16 Jason Merrill + Manfred Hollstein + + * decl.c (grokdeclarator): Don't make 'main(){}' an error with only + -Wreturn-type. + +1999-01-16 Nathan Sidwell + + * cp-tree.h (struct lang_type): Added has_mutable flag. + (CLASSTYPE_HAS_MUTABLE): New macro to access it. + (TYPE_HAS_MUTABLE_P): New macro to read it. + (cp_has_mutable_p): Prototype for new function. + * class.c (finish_struct_1): Set has_mutable from members. + * decl.c (cp_finish_decl): Clear decl's TREE_READONLY flag, if + it contains a mutable. + * typeck.c (cp_has_mutable_p): New function. + +1999-01-15 Mark Mitchell + + * pt.c (process_template_parm): Ignore top-level qualifiers on + non-type parameters. + + * decl.c (start_function): Use current_function_parms in the call + to require_complete_type_for_parms, not the probably empty + DECL_ARGUMENTS. + +1999-01-14 Jason Merrill + + * semantics.c (finish_asm_stmt): Don't warn about redundant volatile. + + * decl2.c (import_export_class): MULTIPLE_SYMBOL_SPACES only means + that we don't suppress the other copies. + * lex.c (handle_cp_pragma): Likewise. + +1999-01-13 Mark Mitchell + + * decl.c (grokdeclarator): Undo 1998-12-14 change. + * tree.c (build_cplus_array_type_1): Likewise. + * pt.c (instantiate_class_template): Remove misleading comment. + (tsubst_aggr_type): Substitute if there are template parameters, + regardless of whether or not they use template arguments. + (unify): Likewise, but for unification. + +1999-01-12 Richard Henderson + + * cp-tree.h (flag_permissive): Declare extern. + +1999-01-06 Mark Mitchell + + * cp-tree.h (IDENTIFIER_TYPENAME_P): Use OPERATOR_TYPENAME_FORMAT + here. + (lang_type): Add is_partial_instantiation. Decrease width of + dummy. + (PARTIAL_INSTANTIATION_P): New macro. + (OPERATOR_TYPENAME_P): Remove. + * decl.c (unary_op_p): Use IDENTIFIER_TYPENAME_P, not + OPERATOR_TYPENAME_P. + (grok_op_properties): Likewise. + * friend.c (do_friend): Handle friends that are member functions + correctly. + * lex.c (init_parse): Use OPERATOR_TYPENAME_FORMAT. + * pt.c (instantiate_class_template): Rework for clarity. Avoid + leaving TYPE_BEING_DEFINED set in obscure cases. Don't do + any more partial instantiation than is absolutely necessary for + implicit typename. Set PARTIAL_INSTANTIATION_P. + (tsubst_decl): Use IDENTIFIER_TYPENAME_P. + * semantics.c (begin_class_definition): Handle partial + specializations of a type that was previously partially + instantiated. + +Wed Jan 6 03:18:53 1999 Mark Elbrecht + + * Make-lang.in (g++.o): Depend on prefix.h. + +1999-01-04 Jason Merrill + + * tree.c (bound_pmf_p): New fn. + * typeck.c (build_c_cast): Use it. + + * decl.c (grok_op_properties): Use same_type_p. + +Tue Dec 22 15:09:25 1998 Kaveh R. Ghazi + + * Makefile.in (cvt.o): Depend on toplev.h. + + * cp-tree.h (check_template_shadow, pod_type_p): Add prototypes. + + * cvt.c: Include toplev.h. + + * except.c (get_eh_caught, get_eh_handlers): Hide prototypes and + definitions. + + * init.c (expand_vec_init): Initialize variable `itype'. + + * lex.c (yyerror): Cast the argument passed to a ctype function to + an unsigned char. + + * method.c (build_mangled_C9x_name): Wrap prototype and definition + in "HOST_BITS_PER_WIDE_INT >= 64". + + * typeck.c (build_binary_op): Mark parameter `convert_p' with + ATTRIBUTE_UNUSED. + +1998-12-22 Mark Mitchell + + * cp-tree.h (TYPE_RAISES_EXCEPTIONS): Improve documentation. + * tree.c (build_exception_variant): Don't crash on empty throw + specs. + +1998-12-18 DJ Delorie + + * cvt.c (convert_to_reference): Check for both error_mark_node + and NULL_NODE after call to convert_for_initialization. + +1998-12-17 Jason Merrill + + * error.c (interesting_scope_p): New fn. + (dump_simple_decl): Use it. + (dump_expr, case CONSTRUCTOR): Force a & for a PMF. + (dump_expr, case OFFSET_REF): Print ->* if appropriate. + +1998-12-16 Mark Mitchell + + * class.c (resolve_address_of_overloaded_function): Do conversion + to correct type here, rather than ... + (instantiate_type): Here. + + * cp-tree.h (DECL_TEMPLATE_PARM_P): New macro. + (DECL_TEMPLATE_TEMPLATE_PARM_P): Use it. + (decl_template_parm_p): Remove. + * decl.c (pushdecl): Don't set DECL_CONTEXT for a template + parameter. + * lex.c (do_identifier): Use DECL_TEMPLATE_PARM_P. + * pt.c (push_inline_template_parms_recursive): Set it. + (decl_template_parm_p): Remove. + (check_template_shadow): Use DECL_TEMPLATE_PARM_P. + (process_template_parm): Set it. + +Wed Dec 16 16:33:58 1998 Dave Brolley + + * lang-specs.h (default_compilers): Pass -MD, -MMD and -MG to cc1plus + if configured with cpplib. + +1998-12-15 Mark Mitchell + + * decl.c (poplevel): Make sure ns_binding is initialized. + + * decl.c (finish_function): Undo inadvertent change in previous + patch. + +1998-12-14 Mark Mitchell + + * class.c (pushclass): Tweak handling of class-level bindings. + (resolve_address_of_overloaded_function): Update pointer-to-member + handling. + (instantiate_type): Likewise. + * cvt.c (cp_convert_to_pointer): Likewise. + * decl.c (pop_binding): Take the DECL to pop, not just the name. + Deal with `struct stat' hack. + (binding_level): Add to documentation. + (push_binding): Clear BINDING_TYPE. + (add_binding): New function. + (push_local_binding): Use it. + (push_class_binding): Likewise. + (poplevel): Adjust calls to pop_binding. + (poplevel_class): Likewise. + (pushdecl): Adjust handling of TYPE_DECLs; add bindings for hidden + declarations to current binding level. + (push_class_level_binding): Likewise. + (push_overloaded_decl): Adjust handling of OVERLOADs in local + bindings. + (lookup_namespace_name): Don't crash when confronted with a + TEMPLATE_DECL. + (lookup_name_real): Do `struct stat' hack in local binding + contexts. + (build_ptrmemfunc_type): Adjust documentation. + (grokdeclarator): Don't avoid building real array types when + processing templates unless really necessary. + (finish_method): Adjust calls to pop_binding. + * decl2.c (reparse_absdcl_as_expr): Recursively call ourselves, + not reparse_decl_as_expr. + (build_expr_from_tree): Deal with a template-id as the function to + call in a METHOD_CALL_EXPR. + * pt.c (convert_nontype_argument): Tweak pointer-to-member handling. + (maybe_adjust_types_For_deduction): Don't do peculiar things with + METHOD_TYPEs here. + (resolve_overloaded_unification): Handle COMPONENT_REFs. Build + pointer-to-member types where necessary. + * tree.c (build_cplus_array_type_1): Don't avoid building real + array types when processing templates unless really necessary. + (build_exception_variant): Compare the exception lists correctly. + +1998-12-13 Mark Mitchell + + * cp-tree.def (CPLUS_BINDING): Update documentation. + * cp-tree.h (LOCAL_BINDING_P): New macro. + (lang_identifier): Rename local_value to bindings. + (tree_binding): Make `scope' of type `void*', not `tree'. + (BINDING_SCOPE): Update documentation. + (IDENTIFIER_LOCAL_VALUE): Remove. + (IDENTIFIER_CLASS_VALUE): Document. + (IDENTIFIER_BINDING): New macro. + (IDENTIFIER_VALUE): Likewise. + (TIME_IDENTIFIER_TIME): Likewise. + (TIME_IDENTIFIER_FILEINFO): Likewise. + (IMPLICIT_TYPENAME_P): Likewise. + (set_identifier_local_value): Remove. + (push_local_binding): New function. + (push_class_binding): Likewise. + * class.c (pushclass): Update comments; use push_class_binding. + * decl.c (set_identifier_local_value_with_scope): Remove. + (set_identifier_local_value): Likewise. + (push_binding): New function. + (pop_binding): Likewise. + (binding_level): Update documentation. Remove shadowed. + (BINDING_LEVEL): New macro. + (free_binding_nodes): New variable. + (poplevel): Adjust for new name-lookup scheme. Don't mess up + BLOCK_VARs when doing for-scope extension. Remove effectively + dead code. + (pushlevel_class): Tweak formatting. + (poplevel_class): Adjust for new name-lookup scheme. + (print_binding_level): Likewise. + (store_bindings): Likewise. + (pushdecl): Likewise. + (pushdecl_class_level): Likewise. + (push_class_level_binding): Likewise. + (push_overloaded_decl): Update comments. Adjust for new + name-lookup scheme. + (lookup_name_real): Likewise. + (lookup_name_current_level): Likewise. + (cp_finish_decl): Likewise. + (require_complete_types_for_parms): Likewise. Remove misleading + #if 0'd code. + (grok_parms): Likewise. Don't call + require_complete_types_for_parms here. + (grok_ctor_properties): Don't treat templates as copy + constructors. + (grop_op_properties): Or as assignment operators. + (start_function): Document. Adjust for new name-lookup scheme. + (finish_function): Likewise. + * decl2.c (do_local_using_decl): Use push_local_binding. + * lex.c (begin_definition_of_inclass_inline): New function, split + out from ... + (do_pending_inlines): Here, and ... + (process_next_inline): Here. + (get_time_identifier): Use TIME_IDENTIFIER_* macros. + (init_filename_times): Likewise. + (extract_interface_info): Likewise. + (ste_typedecl_interface_info): Likewise. + (check_newline): Likewise. + (dump_time_statistics): Likewise. + (handle_cp_pragma): Likewise. + (do_identifier): Adjust for new name-lookup scheme. + * parse.y (function_try_block): Return ctor_initializer_opt value. + (fndef): Use it. + (fn.defpen): Pass appropriate values to start_function. + (pending_inline): Use functor_try_block value, and pass + appropriate values to finish_function. + * pt.c (is_member_template): Update documentation; remove handling + of FUNCTION_DECLs. As per name, this function should deal only in + TEMPLATE_DECLs. + (decl_template_parm_p): Change name of olddecl parameter to decl. + (check_template_shadow): Adjust for new name-lookup scheme. + (lookup_template_class): Likewise. + (tsubst_decl): Tweak so as not to confuse member templates with + copy constructors and assignment operators. + (unify): Handle UNION_TYPEs. + * ptree.c (print_lang_identifier): Adjust for new name-lookup scheme. + (lang_print_xnode): Adjust for new name-lookup scheme. + * typeck.c (mark_addressable): Likewise. + (c_expand_return): Likewise. + +1998-12-08 Jason Merrill + + * decl.c (grokdeclarator): Allow field with same name as class + in extern "C". + + * decl.c (lookup_name_real): Don't limit field lookup to types. + * class.c (check_member_decl_is_same_in_complete_scope): No error + if icv and x are the same. + * lex.c (do_identifier): Tweak error message. + +1998-12-10 Mark Mitchell + + * decl.c (start_enum): Use push_obstacks, not + end_temporary_allocation. + (finish_enum): Call pop_obstacks. + +1998-12-10 Mark Mitchell + + * class.c (instantiate_type): Return error_mark_node rather than + junk. + +1998-12-09 Mark Mitchell + + * cp-tree.h (most_specialized_instantiation): New function. + (print_candidates): Likewise. + * class.c (validate_lhs): Remove. + (resolve_address_of_overloaded_function): New function, split out + and then substantially reworked, from ... + (instantiate_type): Use it. Simplify. + * cvt.c (convert_to_reference): Complain when caller has indicated + that's the right thing to do. Don't crash if instantiate_type + fails. + * pt.c: Substitute `parameters' for `paramters' throughout. + (print_candidates): Don't make it static. + (most_specialized_instantiation): Split out from ... + (most_specialized): Here. + +Wed Dec 9 15:33:01 1998 Dave Brolley + + * lex.c (lang_init_options): Initialize cpplib. + * decl2.c (parse_options,cpp_initialized): Removed. + (lang_decode_option): Move initialization of cpplib to + lang_init_options. + +1998-12-09 Mark Mitchell + + * decl.c (grokdeclarator): Update the name of the TEMPLATE_DECL, as + well as the TYPE_DECL, when a typedef name is assigned to a + previously anonymous type. + +1998-12-08 Andrew MacLeod + + * cp/except.c (call_eh_info): Use __start_cp_handler instead of + __cp_eh_info for getting the eh info pointer. Add table_index to + field list. + (push_eh_cleanup): Don't increment 'handlers' data field. + (process_start_catch_block): Don't set the 'caught' field. + + * cp/exception.cc (CP_EH_INFO): New macro for getting the + exception info pointer within library routines. + (__cp_eh_info): Use CP_EH_INFO. + (__start_cp_handler): Get exception info pointer, set caught field, + and increment the handlers field. Avoids this being done by handlers. + (__uncatch_exception, __check_eh_spec): Use CP_EH_INFO macro. + (uncaught_exception): Use CP_EH_INFO macro. + +Tue Dec 8 10:48:21 1998 Jeffrey A Law (law@cygnus.com) + + * Make-lang.in (cxxmain.o): Depend on $(DEMANGLE_H), not demangle.h + +Mon Dec 7 17:56:06 1998 Mike Stump + + * lex.c (check_newline): Add support for \ as `natural' + characters in file names in #line to be consistent with #include + handling. We support escape processing in the # 1 "..." version of + the command. See also support in cp/lex.c. + +1998-12-07 Zack Weinberg + + * cp/decl2.c: s/data/opts/ when initializing cpp_reader + structure. + +1998-12-07 Jason Merrill + + * decl.c (build_typename_type): Set DECL_ARTIFICIAL. + + * error.c (dump_simple_decl): Also print namespace context. + (dump_function_decl): Likewise. + + * decl2.c (ambiguous_decl): Don't print old value if it's + error_mark_node. + + * decl.c (lookup_name_real): Fix handling of local types shadowed + by a non-type decl. Remove obsolete code. + * cp-tree.h (DECL_FUNCTION_SCOPE_P): New macro. + + * lang-options.h: Add -fpermissive. + * decl2.c: Likewise. + * cp-tree.h: Add flag_permissive. + * decl.c (init_decl_processing): If neither -fpermissive or -pedantic + were specified, set flag_pedantic_errors. + * call.c (build_over_call): Turn dropped qualifier messages + back into pedwarns. + * cvt.c (convert_to_reference): Likewise. + * typeck.c (convert_for_assignment): Likewise. + +1998-12-05 Jason Merrill + + * decl2.c (coerce_new_type): Use same_type_p. + (coerce_delete_type): Likewise. + + * call.c (check_dtor_name): Return 1, not error_mark_node. + +1998-12-04 Jason Merrill + + * lex.c (handle_cp_pragma): Disable #pragma interface/implementation + if MULTIPLE_SYMBOL_SPACES. + + * pt.c (check_template_shadow): New fn. + * decl2.c (grokfield): Use it. + * decl.c (pushdecl): Likewise. + (pushdecl_class_level): Likewise. + (start_method): Likewise. + (xref_tag): Don't try to use 't' if we're defining. + + * call.c (check_dtor_name): Just return an error_mark_node. + * pt.c (lookup_template_class): Complain about using non-template here. + * parse.y (apparent_template_type): Not here. + + * pt.c (check_explicit_specialization): Complain about specialization + with C linkage. + + * lang-options.h: Add -f{no-,}implicit-inline-templates. + + * pt.c (convert_nontype_argument): Don't assume that any integer + argument is intended to be a constant-expression. + +1998-12-03 Mark Mitchell + + * class.c (handle_using_decl): Fix comment. Don't lookup + constructors in base classes. + (validate_lhs): Fix typo in comment. + * search.c (lookup_field_1): Don't return a USING_DECL. + + * cp-tree.h (DECL_ACCESS): Improve documentation. + + * decl.c (expand_static_init): Don't set the initialization-done + flag until the initialization is done. + +1998-12-02 Mark Mitchell + + * decl2.c (validate_nonmember_using_decl): Complain about using + declarations for class members. + +1998-11-29 Jason Merrill + + * typeck2.c (process_init_constructor): Use same_type_p. + + * decl.c (check_tag_decl): Don't warn about null decl inside a + class. + + * pt.c (unify, case OFFSET_TYPE): Pass down 'strict' rather than + UNIFY_ALLOW_NONE. + (convert_nontype_argument): Use TYPE_PTRMEMFUNC_FN_TYPE. + (resolve_overloaded_unification): Strip baselinks. + +Fri Nov 27 13:07:23 1998 Kaveh R. Ghazi + + * g++spec.c: Don't prototype xmalloc. + +1998-11-25 Jason Merrill + + * except.c (expand_throw): Use TYPE_PTR_P to check for pointers. + + * decl.c (check_tag_decl): Do complain about null friend decl at + file scope. + +1998-11-25 Andreas Schwab + + * lex.c (make_lang_type): Clear the whole struct lang_type, not + only the first multiple of sizeof (int). + +1998-11-24 Jason Merrill + + * decl.c (start_decl): An explicit specialization of a static data + member is only a definition if it has an initializer. + + * except.c (expand_throw): Use cp_finish_decl for the throw temp. + * cvt.c (build_up_reference): Pass DIRECT_BIND down into + cp_finish_decl. + * init.c (expand_default_init): Check for DIRECT_BIND instead of + DECL_ARTIFICIAL. + + * call.c (build_over_call): Use build_decl. + + * except.c (expand_throw): Just use convert, not + build_reinterpret_cast. + + * lex.c (handle_generic_pragma): Use token_buffer. + + * decl.c (check_tag_decl): Don't complain about null friend decl. + +1998-11-24 Dave Pitts + + * Make-lang.in (DEMANGLER_PROG): Move the output arguments to the + first position. + * lex.c (check_newline): Use ISALPHA. + (readescape): Use ISGRAPH. + (yyerror): Use ISGRAPH. + +1998-11-24 Nathan Sidwell + + * search.c (get_abstract_virtuals): Do not use initial + CLASSTYPE_ABSTRACT_VIRTUALS. + * typeck2.c (abstract_virtuals_error): Show location of abstract + declaration. + * call.c (build_new_method_call): Use + CLASSTYPE_ABSTRACT_VIRTUAL, rather than recalculate. + * class.c (finish_struct_bits): Don't bother working out whether + get_abstract_virtuals will do anything, just do it. + +1998-11-24 Graham + + * typeck.c (build_component_ref): Remove unused statement. + +1998-11-24 Jason Merrill + + * class.c (add_method): Catch invalid overloads. + + * class.c (add_method): Build up OVERLOADs properly for conversion ops. + * search.c (lookup_conversions): Handle getting real OVERLOADs. + (add_conversions): Likewise. Revert last change. + * call.c (add_conv_candidate): Pass totype to add_candidate instead + of fn. Don't add a new candidate if the last one was for the same + type. + (print_z_candidates): Handle getting a type as a function. + (joust): If we got two conversion candidates to the same type, + just pick one. + (build_object_call): Lose 'templates'. + (build_user_type_conversion_1): Handle getting real OVERLOADs. + +1998-11-23 Jason Merrill + + * typeck2.c (process_init_constructor): If there are elements + that don't have initializers and they need to have constructors + run, supply them with initializers. + + * class.c (finish_struct_1): A class with a 0-width bitfield is + still empty. + +1998-11-23 Mark Mitchell + + * pt.c (instantiate_class_template): Don't try to figure out what + specialization to use for a partial instantiation. Correct + typos in a couple of comments. Avoid calling uses_template_parms + multiple times. + +1998-11-23 Benjamin Kosnik + + * method.c (process_overload_item): Add call to + build_mangled_C9x_name for intTI_type_nodes. + (build_mangled_C9x_name): Add prototype, define. + * decl.c (init_decl_processing): Add names for + TImode_type_node. + +1998-11-23 Jason Merrill + + * parse.y (named_class_head): Update CLASSTYPE_DECLARED_CLASS. + + * class.c (finish_struct_1): Set things up for 0-width bitfields + like we do for others. + + * decl.c (check_tag_decl): New fn. + (shadow_tag): Split out from here. + * decl2.c (grok_x_components): Call it. + +1998-11-22 Jason Merrill + + * decl.c: Lose warn_about_return_type. + (grokdeclarator): Always complain about implicit int, except for + `main () { ... }'. + + * decl.c (tag_name): New fn. + (xref_tag): Complain about using typedef-name after class-key. + + * init.c (expand_vec_init): Also keep going if from_array. + + * tree.c (is_overloaded_fn): Also handle the output of + build_offset_ref. + + * decl.c (grokdeclarator): Use constructor_name when comparing + field name against enclosing class. + * class.c (finish_struct_anon): Likewise. + +1998-11-22 Mark Mitchell + + * decl.c (poplevel): Remove code to handle KEEP == 2. + (finish_function): Don't confuse BLOCK-order when + processing a destructor. + +1998-11-21 Jason Merrill + + * decl.c (require_complete_types_for_parms): Call layout_decl + after we've completed the type. + +1998-11-21 Martin von Löwis + + * decl2.c (validate_nonmember_using_decl): Allow using templates + from the global namespace. + +1998-11-21 Jason Merrill + + Handle specifying template args to member function templates. + * tree.c (build_overload): Always create an OVERLOAD for a template. + * search.c (add_conversions): Handle finding an OVERLOAD. + * decl2.c (check_classfn): Likewise. + * lex.c (identifier_type): See through a baselink. + * parse.y (do_id): Don't call do_identifier if we got a baselink. + * class.c (instantiate_type, case TREE_LIST): Recurse. + + * decl.c (grokdeclarator): Allow a boolean constant for array + bounds, odd as that sounds. + + * pt.c (unify): Be more strict about non-type parms, except for + array bounds. + (UNIFY_ALLOW_INTEGER): New macro. + +1998-11-19 Manfred Hollstein + + * Make-lang.in (mandir): Replace all uses of $(mandir) by $(man1dir). + +1998-11-19 Jason Merrill + + * semantics.c (begin_class_definition): Call + maybe_process_partial_specialization before push_template_decl. + Don't call push_template_decl for a specialization. + * search.c (lookup_field): Do return a member template class. + * decl2.c (handle_class_head): Handle member template classes. + + * decl.c (grokdeclarator): A parm type need not be complete. + + * pt.c (convert_nontype_argument): Fix thinko. + +1998-11-18 Mark Mitchell + + * cp-tree.h (PTRMEM_CST_CLASS): Fix typo. + (global_delete_fndecl): New variable. + * decl.c (global_delete_fndecl): Define it. + (init_decl_processing): Set it. + * init.c (build_builtin_delete_call): Use it. + * tree.c (mapcar): Recursively call mapcar for the type of EXPR + nodes. + +1998-11-18 Jason Merrill + + * decl.c (cplus_expand_expr_stmt): Always complain about unresolved + type. + + * tree.c (lvalue_p_1): An INDIRECT_REF to a function is an lvalue. + * call.c (build_object_call): Also support references to functions. + * typeck.c (convert_for_initialization): Don't decay a function + if the target is a reference to function. + + * search.c (add_conversions): Get all the overloads from a class. + + * decl.c (grok_ctor_properties): Complain about any constructor + that will take a single arg of the class type by value. + + * typeck2.c (build_functional_cast): Can't create objects of + abstract classes this way. + * cvt.c (ocp_convert): Likewise. + + * decl.c (grokfndecl): Member functions of local classes are not + public. + +1998-11-18 Mark Mitchell + + * Make-lang.in (cc1plus): Add dependency on hash.o. + +1998-11-18 Jason Merrill + + * search.c (get_abstract_virtuals): Complain about virtuals with + no final overrider. + * typeck2.c (abstract_virtuals_error): Remove handling for virtuals + with no final overrider. + * class.c (override_one_vtable): Don't set DECL_ABSTRACT_VIRTUAL_P + on virtuals with no final overrider. + + * lex.c (reinit_parse_for_block): Add a space after the initial ':'. + + * class.c (finish_struct_1): Don't remove zero-width bit-fields until + after layout_type. + + * friend.c (do_friend): Don't set_mangled_name_for_decl. + + * class.c (finish_struct_anon): Complain about non-fields. + * decl2.c (build_anon_union_vars): Likewise. + + * decl.c (grokdeclarator): Normal data members can't have the same + name as the class, either. + * class.c (finish_struct_anon): Neither can members of an + anonymous union. + +1998-11-17 Mark Mitchell + + * cp-tree.h (TYPE_ALIAS_SET): Document language-dependent uses. + (TYPE_BINFO): Likewise. + (IS_AGGR_TYPE): Tweak. + (SET_IS_AGGR_TYPE): New macro. + (CLASS_TYPE_P): Tweak. + (lang_type): Group mark bitfields together. Remove linenum. + (CLASSTYPE_SOURCE_LINE): Remove macro. + (CLASSTYPE_MARKED_N): New macro. + (SET_CLASSTYPE_MARKED_N): Likewise. + (CLEAR_CLASSTYPE_MARKED_N): Likewise. + (CLASS_TYPE_MARKED_*): Use them. + (SET_CLASSTYPE_MARKED_*): Likewise. + (CLEAR_CLASSTYPE_MARKED_*): Likewise. + (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO): Likewise. + (TYPE_TEMPLATE_INFO): Handle TEMPLATE_TEMPLATE_PARMs as well. + (TYPENAME_TYPE_FULLNAME): Use TYPE_BINFO rather than CLASSTYPE_SIZE. + * class.c (class_cache_obstack): New variable. + (class_cache_firstobj): Likewise. + (finish_struct): Don't set CLASSTYPE_SOURCE_LINE. + (pushclass): Free the cache, when appropriate. + (popclass): Tidy. + (maybe_push_cache_obstack): Use class_cache_obstack. + * decl.c (include hash.h). + (typename_hash): New function. + (typename_compare): Likewise. + (build_typename_type): Check the hash table to avoid creating + duplicates. + (build_ptrmemfunc_type): Use SET_IS_AGGR_TYPE. + (grokdeclarator): Use CLASS_TYPE_P. + (xref_basetypes): Likewise. + (start_function): Likewise. Don't put current_class_ref on the + permanent obstack. + * error.c (dump_type_real): Use TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO + and TYPE_TI_ARGS. + * lex.c (note_got_semicolon): Use CLASS_TYPE_P. + (make_lang_type): Don't create TYPE_LANG_SPECIFIC and associated + fields for types other than class types. Do clear TYPE_ALIAS_SET + for types other than class types, though. + * method.c (build_overload_identifier): Use CLASS_TYPE_P and + TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO. + * pt.c (process_template_parm): Don't set + CLASSTYPE_GOT_SEMICOLON. + (lookup_template_class): Use TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO. + Coerce arguments on the momentary obstack. + (for_each_template_parm): Use TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO. + (instantiate_class_template): Calculate template arguments on the + momentary obstack. Tidy. + (tsubst_template_arg_vector): Use make_temp_vec. + (tsubst_aggr_type): Put template arguments on the momentary + obstack. + (tsubst_decl): Likewise. + (tsubst): Copy the array bounds index to the permanent obstack + before building index types. Use new macros. + (unify): Use new macros. + (do_type_instantiation): Likewise. + * search.c (lookup_fnfields_1): Use new macros. + (dfs_pushdecls): Build envelopes on the cache obstack. + (dfs_compress_decls): Use new macros. + (push_class_decls): Build on the cache obstack. + * semantics.c (finish_typeof): Don't set CLASSTYPE_GOT_SEMICOLON. + * sign.c (build_signature_pointer_or_reference_type): Use + SET_IS_AGGR_TYPE. + * tree.c (make_binfo): Check CLASS_TYPE_P. + (copy_template_template_parm): Adjust. + (make_temp_vec): Use push_expression_obstack. + * typeck.c (complete_type): Use new macros. + (comptypes): Likewise. + +1998-11-17 Jason Merrill + + * pt.c (tsubst): Add diagnostics for invalid array, reference + and pointer to member types. + +1998-11-16 Jason Merrill + + * typeck2.c (my_friendly_abort): Don't fatal twice in a row. + + * typeck.c (c_expand_start_case): Use build_expr_type_conversion. + Simplify. + + * parse.y (structsp): Fix cut-and-paste error. + + * init.c (build_new): Complain about non-integral size. + + * parse.y (unary_expr): Complain about defining types in sizeof. + + * typeck.c (expr_sizeof): Complain about sizeof an overloaded fn. + + * rtti.c (build_x_typeid): Complain about typeid without + including . + (get_typeid): Likewise. Complain about typeid of incomplete type. + (get_tinfo_fn_dynamic): Likewise. + (get_typeid_1): Not static anymore. + * except.c (build_eh_type_type): Use get_typeid_1. + + * rtti.c (build_dynamic_cast_1): Give errors for dynamic_cast to + ambiguous or private bases. Fix warning for reference cast. + +1998-11-16 Mark Mitchell + + * cp-tree.h (DECL_TEMPLATE_INSTANTIATED): New macro. + * decl.c (duplicate_decls): Remove special-case code to deal with + template friends, and just do the obvious thing. + * pt.c (register_specialization): Tweak for clarity, and also to + clear DECL_INITIAL for an instantiation before it is merged with a + specialization. + (check_explicit_specialization): Fix indentation. + (tsubst_friend_function): Handle both definitions in friend + declaration and outside friend declarations. + (tsubst_decl): Don't clear DECL_INITIAL for an instantiation. + (regenerate_decl_from_template): Tweak accordingly. + (instantiate_decl): Likewise. + +1998-11-16 Jason Merrill + + * decl.c (cplus_expand_expr_stmt): Promote warning about naked + member function reference to error. + * cvt.c (ocp_convert): Complain about converting an overloaded + function to void. + + * init.c (build_offset_ref): Just return a lone static member + function. + + * decl.c (cp_finish_decl): Only complain about real CONSTRUCTORs, + not internal ones. + + * typeck.c (build_binary_op_nodefault): Improve error handling. + + * decl.c (grokfndecl): Complain about making 'main' a template. + + * typeck.c (string_conv_p): Don't convert from wchar_t[] to char*. + + * call.c (build_method_call): Handle a BIT_NOT_EXPR around a + TYPE_DECL in a template. + +1998-11-15 Jason Merrill + + * typeck2.c (my_friendly_abort): Add URL in the other case, too. + + * decl.c (struct cp_function): Add named_label_uses. + (push_cp_function_context): Save it. + (pop_cp_function_context): Restore it. + (define_label): Also complain about jumping into the scope of + non-POD objects that don't have constructors. + * tree.c (pod_type_p): New fn. + + * pt.c (instantiate_class_template): Clear TYPE_BEING_DEFINED sooner. + * rtti.c (synthesize_tinfo_fn): Call import_export_decl here. + (get_tinfo_fn): Not here. + * repo.c (repo_get_id): Abort if we get called for an incomplete + type. + +1998-11-13 Mark Mitchell + + * except.c (expand_throw): Make sure first argument to + __cp_push_exception is of type `void*' to avoid spurious error + messages. + +1998-11-11 Jason Merrill + + * pt.c (try_one_overload): Take orig_targs again. Only check for + mismatches against them; we don't care what a previous call found. + (resolve_overloaded_unification): Adjust. + + * search.c (lookup_field): Don't return anything for a non-type + field from a dependent type. + * decl.c (grokdeclarator): Resolve SCOPE_REFs of the current class + in an array declarator. + (start_decl): Push into the class before looking for the field. + +1998-11-08 Mark Mitchell + + * method.c (build_overload_value): Handle REFERENCE_TYPE. + +1998-11-08 Martin von Löwis + + * decl.c (grokdeclarator): Allow namespace-scoped members if they + are friends. + +1998-11-08 Jason Merrill + + * pt.c (tsubst_decl): Don't mess with the global value of an + un-mangled DECL_ASSEMBLER_NAME. + +1998-11-03 Christopher Faylor + + * decl.c (init_decl_processing): Remove CYGWIN conditional + since CYGWIN is now able to deal with trapping signals. + +Sat Nov 7 15:48:02 1998 Kaveh R. Ghazi + + * cp-tree.h: Don't include gansidecl.h. + * exception.cc: Include gansidecl.h (since we don't include config.h) + * g++spec.c: Don't include gansidecl.h. + +1998-11-06 Mark Mitchell + + * cp-tree.h (lang_decl_flags): Add defined_in_class. Decrease + size of dummy. + (DECL_DEFINED_IN_CLASS_P): New macro. + (TEMPLATE_PARMS_FOR_INLINE): Document. + (check_static_variable_definition): New function. + * decl.c (cp_finish_decl): Set DECL_DEFINED_IN_CLASS_P, if + appropriate. + (check_static_variable_definition): Split out from ... + (grokdeclarator): Here. + * pt.c (check_default_tmpl_args): New function, split out from ... + (push_template_decl_real): Here. + (instantiate_template): Fix comment. + +1998-11-04 Mark Mitchell + + * cp-tree.h (CP_TYPE_CONST_P): Make {0,1}-valued. + (CP_TYPE_VOLATILE_P): Likewise. + (CP_TYPE_RESTRICT_P): Likewise. + +1998-11-03 Mark Mitchell + + * pt.c (tsubst): Use build_index_type, not build_index_2_type. + +1998-11-02 Jason Merrill + + * class.c (instantiate_type): Be more helpful. + + * decl2.c (import_export_decl): Call import_export_class. + + * cp-tree.h (EMPTY_CONSTRUCTOR_P): Check !TREE_HAS_CONSTRUCTOR. + * decl2.c (build_expr_from_tree): Propagate TREE_HAS_CONSTRUCTOR. + * pt.c (tsubst_copy): Likewise. + +1998-11-02 Mark Mitchell + + * init.c (expand_vec_init): Fix off-by-one error. + +1998-11-02 Alexandre Oliva + + * parse.y (apparent_template_type): New type. + (named_complex_class_head_sans_basetype): Use it. + * Makefile.in (CONFLICTS): One new conflict. + * parse.c: Regenerated. + +1998-11-01 Mark Mitchell + + * cp-tree.h (COMPARE_STRICT): New macro. + (COMPARE_BASE): Likewise. + (COMPARE_RELAXED): Likewise. + (COMPARE_REDECLARATION): Likewise. + (same_type_p): Likewise. + (same_or_base_type_p): Likewise. + * call.c (standard_conversion): Use them, in place of comptypes + with numeric arguments. + (reference_binding): Likewise. + (convert_like): Likewise. + (build_over_call): Likewise. + (is_subseq): Likewise. + (is_properly_derived_from): Likewise. + (compare_ics): Likewise. + (joust): Likewise. + * class.c (delete_duplicate_fields_1): Likewise. + (resolves_to_fixed_type_p): Likewise. + (instantiate_type): Likewise. Remove #if 0'd code. + * decl.c (decls_match): Likewise. Use COMPARE_REDECLARATION here. + (pushdecl): Likewise. + (lookup_name_real): Likewise. + (grokdeclarator): Likewise. Check for illegal array declarations. + (grokparms): Likewise. + (grok_op_properties): Likewise. + * decl2.c (check_classfn): Likewise. + * friend.c (is_friend): Likewise. + (make_friend_class): Likewise. + * init.c (expand_aggr_init): Likewise. + (expand_vec_init): Likewise. + * pt.c (is_member_template_class): Remove declaration. + (is_specialization_of): Use COMPARE_* and new macros. + (comp_template_parms): Likewise. + (convert_nontype_argument): Likewise. + (coerce_template_template_parms): Likewise. + (template_args_equal): Likewise. + (lookup_template_class): Likewise. + (type_unification_real): Likewise. + (unify): Likewise. + (get_bindings_real): Likewise. + * search.c (covariant_return_p): Likewise. + (get_matching_virtual): Likewise. + * sig.c (match_method_types): Likewise. + * tree.c (vec_binfo_member): Likewise. + (cp_tree_equal): Likewise. + * typeck.c (common_type): Likewise. + (comp_array_types): Likewise. Get issues involving unknown array + bounds right. + (comptypes): Update comments. Use new flags. + (comp_target_types): Use new macros. + (compparms): Likewise. + (comp_target_parms): Likewise. + (string_conv_p): Likewise. + (build_component_ref): Likewise. + (build_indirect_ref): Likewise. + (build_conditional_expr): Likewise. + (build_static_cast): Likewise. + (build_reinterpret_cast): Likewise. + (build_const_cast): Likewise. + (build_modify_expr): Likewise. + (convert_for_assignment): Likewise. + (comp_ptr_ttypes_real): Likewise. + (ptr_reasonably_similar): Likewise. + (comp_ptr_ttypes_const): Likewise. + +1998-10-31 Jason Merrill + + * rtti.c (build_dynamic_cast_1): Fix cut-and-paste error. + +1998-10-30 Mark Mitchell + + * decl2.c (delete_sanity): Pass integer_zero_node, not + integer_two_node, to build_vec_delete. + * init.c (build_array_eh_cleanup): Remove. + (expand_vec_init_try_block): New function. + (expand_vec_init_catch_clause): Likewise. + (build_vec_delete_1): Don't deal with case that auto_delete_vec + might be integer_two_node anymore. + (expand_vec_init): Rework for initialization-correctness and + exception-correctness. + * typeck2.c (process_init_constructor): Make mutual exclusivity + of cases more obvious. + +1998-10-29 Jason Merrill + + * decl.c (lookup_name_real): OK, only warn if not lexing. + Simplify suggested fix. + + * cp-tree.h (IDENTIFIER_MARKED): New macro. + * search.c (lookup_conversions): Use breadth_first_search. + (add_conversions): Avoid adding two conversions to the same type. + (breadth_first_search): Work with base binfos, rather + than binfos and base indices. + (get_virtual_destructor): Adjust. + (tree_has_any_destructor_p): Adjust. + (get_matching_virtual): Adjust. + + * pt.c (push_template_decl_real): Generalize check for incorrect + number of template parms. + (is_member_template_class): #if 0. + +1998-10-29 Richard Henderson + + * Makefile.in (cc1plus): Put CXX_OBJS, and thence @extra_cxx_objs@, + last. + +1998-10-28 Zack Weinberg + + * lex.c: Call check_newline from lang_init always. After + calling cpp_start_read, set yy_cur and yy_lim to read from the + cpplib token buffer. + +1998-10-28 Jason Merrill + + * class.c (instantiate_type): Don't consider templates for a normal + match. + + * class.c (finish_struct_1): Don't complain about non-copy + assignment ops in union members. + + * class.c (build_vtable): Don't pass at_eof to import_export_vtable. + (prepare_fresh_vtable): Likewise. + (finish_struct_1): Don't call import_export_class. + * decl2.c (finish_vtable_vardecl): Do import/export stuff. + (finish_prevtable_vardecl): Lose. + (finish_file): Don't call it. + * pt.c (instantiate_class_template): Likewise. + * cp-tree.h: Remove it. + + * init.c (build_delete): Reset TYPE_HAS_DESTRUCTOR here. + * decl.c (finish_function): Not here. + (start_function): Do set DECL_INITIAL. + + * pt.c (push_template_decl_real): Complain about default template + args for enclosing classes. + + * call.c (add_function_candidate): Treat conversion functions + as coming from the argument's class. + * cp-tree.h (DECL_CONV_FN_P): New fn. + (DECL_DESTRUCTOR_P): Also check DECL_LANGUAGE. + * class.c (add_method): Use DECL_CONV_FN_P. + * decl2.c (check_classfn): Likewise. + * error.c (dump_function_name): Likewise. + (dump_function_decl): Likewise. + * pt.c (fn_type_unification): Likewise. + * search.c (add_conversions): Likewise. + +1998-10-27 Jason Merrill + + * lex.c (do_identifier): Also generate LOOKUP_EXPR for RESULT_DECL. + * method.c (hack_identifier): Also check for using RESULT_DECL + from outer context. + +1998-10-27 Mark Mitchell + + * decl.c (grokdeclarator): Use type_quals, rather than constp, + consistently. + +1998-10-27 Jason Merrill + + * call.c (standard_conversion): instantiate_type here. + (reference_binding): And here. + (implicit_conversion): Not here. + (build_op_delete_call): No need to cons up an OVERLOAD. + * cvt.c (cp_convert_to_pointer): instantiate_type here. + (convert_to_reference): And here. + * decl.c (grok_reference_init): Not here. + (grokparms): Or here. + * typeck2.c (digest_init): Or here. + * typeck.c (decay_conversion): Take the address of overloaded + functions, too. + (require_instantiated_type): Lose. + (convert_arguments): Don't handle unknown types here. + (build_c_cast): Likewise. + (build_binary_op): Gut. + (build_conditional_expr): Don't require_instantiated_type. + (build_modify_expr): Likewise. + (build_static_cast): Don't instantiate_type. + (build_reinterpret_cast): Likewise. + (build_const_cast): Likewise. + (convert_for_initialization): Likewise. + (build_ptrmemfunc): Use type_unknown_p. + (convert_for_assignment): Also do default_conversion on overloaded + functions. Hand them off to ocp_convert. + +1998-10-26 Mark Mitchell + + * error.c (dump_decl): Deal with TEMPLATE_DECLs that are + VAR_DECLs. Handle vtables whose DECL_CONTEXT is not a type. + + * class.c (finish_struct_1): Use build_cplus_array_type to build + array types. + * decl.c (init_decl_processing): Likewise. + * except.c (expand_end_eh_spec): Likewise. + * search.c (expand_upcast_fixups): Simplify very slightly. + +1998-10-26 Jason Merrill + + * decl.c (grokdeclarator): Complain about a variable using + constructor syntax coming back null from start_decl. + + * friend.c (make_friend_class): Complain about trying to make + a non-class type a friend. + + * decl.c (grokfndecl): Set DECL_INITIAL for a defn here. + (start_function): Not here. + +1998-10-26 Brendan Kehoe + + * decl.c (grokdeclarator): Disallow `explicit' in a friend declaration. + +1998-10-26 Jason Merrill + + * typeck2.c (process_init_constructor): Only skip anonymous fields + if they are bitfields. + + * cp-tree.def (TYPEOF_TYPE): New code. + * error.c (dump_type_real): Handle it. + * pt.c (tsubst): Likewise. + * tree.c (search_tree): Likewise. + * semantics.c (finish_typeof): New fn. + * parse.y (typespec): Use it. + * cp-tree.h: Declare it. + +1998-10-26 Manfred Hollstein + + * cp-tree.h (FORMAT_VBASE_NAME): Make definition unconditional. + +1998-10-26 Jason Merrill + + * typeck.c (convert_arguments): Don't handle pmf references + specially. + + * init.c (build_member_call): Don't try to convert to the base type + if it's ambiguous or pedantic. + + * typeck2.c (check_for_new_type): Only depend on pedantic for + C-style casts. + +1998-10-25 Mark Mitchell + + * decl.c (grokdeclarator): Set DECL_NONCONVERTING_P for all + non-converting constructors. + +1998-10-24 Martin von Löwis + + * gxxint.texi: Correct documentation for n, N, Q, and B. + +1998-10-23 Martin von Löwis + + * parse.y (condition): Convert VAR_DECL from reference to indirect + reference. + +1998-10-23 Andrew MacLeod + + * exception.cc (__cp_pop_exception): Free the original exception + value, not the potentially coerced one. + +1998-10-23 Mark Mitchell + + * Makefile.in (hash.h): Run gperf when necessary. + + * cp-tree.h (CP_TYPE_READONLY): Remove. + (CP_TYPE_VOLATILE): Likewise. + (CP_TYPE_QUALS): New macro. + (CP_TYPE_CONST_P): Likewise. + (CP_TYPE_VOLATILE_P): Likewise. + (CP_TYPE_RESTRICT_P): Likewise. + (CP_TYPE_CONST_NON_VOLATILE_P): Likewise. + (cp_build_type_variant): Rename to ... + (cp_build_qualified_type): New function. + (c_apply_type_quals_to_decl): Declare. + (SIGNATURE_POINTER_NAME_FORMAT): Modify to allow `restrict'. + (SIGNATURE_REFERENCE_NAME_FORMAT): Likewise. + (cp_type_qual_from_rid): New function. + (compparms): Remove unused parameter. All callers changed. + (cp_type_quals): New function. + (at_least_as_qualified_p): Likewise. + (more_qualified_p): Likewise. + + * call.c (standard_conversion): Replace calls to + cp_build_type_variant with cp_build_qualified_type. Use + CP_TYPE_QUALS to get qualifiers and at_least_as_qualified_p to + compare them. Use CP_TYPE_* macros to check qualifiers. + (reference_binding): Likewise. + (implicit_conversion): Likewise. + (add_builtin_candidates): Likewise. + (build_over_call): Likewise. + * class.c (overrides): Compare all qualifiers, not just `const', + on method declarations. + * cvt.c (convert_to_reference): More CP_TYPE_QUALS conversion, etc. + (convert_pointer_to_real): Likewise. + (type_promotes_to): Likewise. + * decl.c (check_for_uninitialized_const_var): New function. + (init_decl_processing): More CP_TYPE_QUALS conversion, etc. + (cp_finish_decl): Use check_for_uninitialized_const_var. + (grokdeclarator): More CP_TYPE_QUALS conversion, etc. Update to + handle `restrict'. + (grok_ctor_properties): Likewise. + (grok_op_properties): Likewise. + (start_function): Likewise. + (rever_static_member_fn): Likewise. + * decl2.c (grok_method_quals): Likewise. + (grokfield): Likewise. + * error.c (dump_readonly_or_volatile): Rename to ... + (dump_qualifiers): New function. Handle `restrict'. + (dump_type_real): Use it. + (dump_aggr_type): Likewise. + (dump_type_prefix): Likewise. + (dump_type_suffix): Likewise. + (dump_function_decl): Likewise. + (cv_as_string): Likewise. + * gxx.gperf: Add __restrict and __restrict__. + * gxxint.texi: Document `u' as used for `__restrict', and a few + other previously undocumented codes. + * hash.h: Regenerated. + * init.c (expand_aggr_init): More CP_TYPE_QUALS conversion, etc. + (build_member_call): Likewise. + (build_new_1): Likewise. + * lex.c (init_parse): Add entry for RID_RESTRICT. + (cons_up_default_function): More CP_TYPE_QUALS conversion, etc. + (cp_type_qual_from_rid): Define. + * lex.h (enum rid): Add RID_RESTRICT. + * method.c (process_modifiers): Deal with `restrict'. + * parse.y (primary): More CP_TYPE_QUALS conversion, etc. + * parse.c: Regenerated. + * pt.c (convert_nontype_argument): More CP_TYPE_QUALS conversion, etc. + (tsubst_aggr_type): Likewise. + (tsubst): Likewise. + (check_cv_quals_for_unify): Likewise. + (unify): Likewise. + * rtti.c (init_rtti_processing): Likewise. + (build_headof): Likewise. + (get_tinfo_var): Likewise. + (buidl_dynamic_cast_1): Likewise. Fix `volatile' handling. + (expand_class_desc): Likewise. + (expand_attr_desc): Likewise. + (synthesize_tinfo_fn): Likewise. + * search.c (covariant_return_p): Likewise. Fix `volatile' handling. + (get_matching_virtual): Likewise. + (expand_upcast_fixups): Likewise. + * sig.c (build_signature_pointer_or_reference_name): Take + type_quals, not constp and volatilep. + (build_signature_pointer_or_reference_type): Likewise. + (match_method_types): More CP_TYPE_QUALS conversion, etc. + (build_signature_pointer_constructor): Likewise. + (build_signature_method_call): Likewise. + * tree.c (build_cplus_array_type): Likewise. + (cp_build_type_variant): Rename to ... + (cp_build_qualified_type): New function. Deal with `__restrict'. + (canonical_type_variant): More CP_TYPE_QUALS conversion, etc. + (build_exception_variant): Likewise. + (mapcar): Likewise. + * typeck.c (qualif_type): Likewise. + (common_type): Likewise. + (comptypes): Likewise. + (comp_cv_target_types): Likewise. + (at_least_as_qualified_p): Define. + (more_qualified_p): Likewise. + (comp_cv_qualification): More CP_TYPE_QUALS conversion, etc. + (compparms): Likewise. + (inline_conversion): Likewise. + (string_conv_p): Likewise. + (build_component_ref): Likewise. + (build_indirect_ref): Likewise. + (build_array_ref): Likewise. + (build_unary_op): Likewise. + (build_conditional_expr): Likewise. + (build_static_cast): Likewise. + (build_c_cast): Likewise. + (build_modify_expr): Likewise. + (convert_For_assignment): Likewise. + (comp_ptr_ttypes_real): Likewise. + (cp_type_quals): New function. + +1998-10-23 Jason Merrill + + * cp-tree.h (CP_TYPE_READONLY): New macro to handle arrays. + (CP_TYPE_VOLATILE): Likewise. + * decl.c (grokdeclarator): Use them. + * tree.c (canonical_type_variant): Likewise. + +1998-10-22 Martin von Löwis + + * parse.y (named_class_head): Push into class while parsing the + base class list. + * decl2.c (push_scope, pop_scope): New functions. + * cp-tree.h: Declare them. + * init.c (build_new_1): Delay cleanup until end of full expression. + +1998-10-21 Jason Merrill + + * typeck.c (build_component_ref): Use of a type here is an error. + +1998-10-19 Jason Merrill + + Revamp references to member functions. + * method.c (hack_identifier): Call build_component_ref for a + reference to a member function. + * typeck.c (build_component_ref): Only return a single function + if it's static. Otherwise, return a COMPONENT_REF. + (build_x_function_call): Handle a COMPONENT_REF. + (build_unary_op): Handle all unknown-type things. + * decl2.c (arg_assoc): Handle COMPONENT_REF. + * class.c (instantiate_type): Complain if the function we get is a + nonstatic member function. Remove code for finding "compatible" + functions. + * pt.c (tsubst_copy): Handle NOP_EXPR. + * tree.c (build_dummy_object): New fn. + (maybe_dummy_object): New fn. + (is_dummy_object): New fn. + * cp-tree.h: Declare them. + * cvt.c (cp_convert_to_pointer): Use maybe_dummy_object. + * error.c (dump_expr, case OFFSET_REF): Use is_dummy_object. + * init.c (build_member_call): Use maybe_dummy_object and + is_dummy_object. + (build_offset_ref): Use maybe_dummy_object. + (resolve_offset_ref): Use is_dummy_object. + * typeck.c (build_x_function_call): Call build_dummy_object. + (unary_complex_lvalue): Call is_dummy_object. + + * typeck.c (build_component_addr): Make sure field is a field. + + * call.c (build_new_op): Delete obsolete code. + + * pt.c (tsubst, TEMPLATE*PARM*): Abort if we don't have any args. + +1998-10-18 Martin von Löwis + + * decl2.c (validate_nonmember_using_decl): Fix using-directives of + std if std is ignored. + +1998-10-18 Jason Merrill + + * decl.c (grokvardecl): Fix thinko. + + * decl.c (grokdeclarator): Embedded attrs bind to the right, + not the left. + + * parse.y (fn.def2): Fix 'attrs' format. + +1998-10-18 Alastair J. Houghton + + * Makefile.in (CONFLICTS): Update. + * parse.y (expr_or_declarator_intern): New rule. + (expr_or_declarator, direct_notype_declarator, primary, + functional_cast): Use it. + (notype_declarator_intern): New rule. + (notype_declarator, complex_notype_declarator): Use it. + +1998-10-17 Jason Merrill + + * decl.c (grokfndecl): Set DECL_CONTEXT to namespace if appropriate. + (grokvardecl): Likewise. + +Sat Oct 17 23:27:20 1998 Kaveh R. Ghazi + + * class.c (make_method_vec): Cast 1st argument of `bzero' to (PTR). + (add_method): Likewise for arguments 1 & 2 of `bcopy'. + + * decl.c (signal_catch): Mark with ATTRIBUTE_NORETURN. + + * pt.c (process_partial_specialization): Cast 1st argument of + `bzero' to (PTR). + + * tree.c (build_base_fields): Cast `base_align' to (int) when + comparing against one. + +1998-10-16 Mark Mitchell + + * decl.c (lookup_name_real): Handle template parameters for member + templates where said parameters have the same name as the + surrounding class. + + * decl.c (expand_static_init): Build cleanups before entering the + anonymous function used to do them to avoid access-checking + confusion. + + * decl.c (grokfndecl): Add back call to cplus_decl_attributes + accidentally removed by previous change, and make DECL_RTL here. + * class.c (add_method): Don't make DECL_RTL here. + + * pt.c (for_each_template_parm): Don't examine uninstantiated + default arguments. + +1998-10-16 Dave Brolley + + * lex.c (real_yylex): Fix unaligned access of wchar_t. + +1998-10-16 Mark Mitchell + + * 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 + processing_template_decl. + +1998-10-16 Jason Merrill + + * typeck.c (build_indirect_ref): Complain about a pointer to data + member, too. + * typeck2.c (build_m_component_ref): Don't indirect a pointer to + data member. + * init.c (resolve_offset_ref): Don't undo the above. + + * cp-tree.h (DECL_C_BIT_FIELD, SET_DECL_C_BIT_FIELD): New macros. + (struct lang_decl_flags): Add `bitfield'. + * class.c (finish_struct_1): Use DECL_C_BIT_FIELD instead of + DECL_BIT_FIELD. + * decl2.c (grokbitfield, grok_alignof): Likewise. + * init.c (build_offset_ref): Likewise. + * typeck.c (build_component_addr, expr_sizeof): Likewise. + * cvt.c (build_up_reference): Don't crash if taking the address + returns error_mark_node. + + * decl.c (grokfndecl): Also check ctype when checking for ::main(). + +1998-10-15 Jason Merrill + + * decl.c (grokfndecl): ::main and __builtin_* get C linkage. + Do mangling here. + (grokdeclarator): Instead of here. + * friend.c (do_friend): Lose special handling of ::main and + __builtin_*. + * cp-tree.h (DECL_MAIN_P): Check for C linkage. + + * spew.c (yylex): Clear looking_for_typename if we got + 'enum { ... };'. + +1998-10-15 Mark Mitchell + + * class.c (maybe_warn_about_overly_private_class): Improve error + messages for class with only private constructors. + + * cp-tree.def (TYPENAME_TYPE): Add to documentation. + * cp-tree.h (TYPENAME_TYPE_FULLNAME): Document. + (build_typename_type): New function. + * decl.c (build_typename_type): Broken out from ... + (make_typename_type): Use it. + * search.c (lookup_field): Likewise. + +1998-10-14 Benjamin Kosnik + + * pt.c (convert_nontype_argument): Check against type_referred_to. + * decl.c (grokvardecl): Check for declarator name before building + DECL_ASSEMBLER_NAME. + +1998-10-14 Mark Mitchell + + * pt.c (lookup_template_class): Add comment. + (instantiate_class_template): Don't mark the _TYPE node for + member class templates as an instantiation. + +1998-10-14 Jason Merrill + + * decl.c (grokfndecl): Fix my thinko. + +1998-10-13 Jason Merrill + + * tinfo2.cc (fast_compare): Remove. + (before): Just use strcmp. + * tinfo.cc (operator==): Just use strcmp. + +1998-10-13 Klaus-Georg Adams + + * decl.c (grokfndecl): Don't check for linkage in `extern "C"' + declarations. + +1998-10-13 Mark Mitchell + + * cp-tree.h (specializations_of_same_template_p): Remove. + * search.c (get_template_base): Don't use it. + (get_template_base_recursive): Likewise. + * pt.c (specializations_of_same_template_p): Remove. + (unify): Don't use it. + (lookup_template_class): Find the correct parent when setting + CLASSTYPE_TI_TEMPLATE. + +1998-10-12 Jason Merrill + + * tinfo.cc (operator==): Always compare names. + +1998-10-12 Herman ten Brugge + + * decl.c (start_function): Fix cut-and-paste error. + +1998-10-12 Jason Merrill + + * inc/typeinfo: Add #pragma interface. + (operator!=): Just call operator==. + * tinfo.cc: Add #pragma implementation. + (operator==): Move from inc/typeinfo and tinfo2.cc. + Check __COMMON_UNRELIABLE instead of _WIN32. + + * typeck2.c (my_friendly_abort): Add URL. + +1998-10-12 Alastair J. Houghton + + * decl.c (start_method): Added extra parameter for attributes. + * cp-tree.h (start_method): Update prototype. + * parse.y (fn.def2): Update start_method parameter list. + +1998-10-11 Mark Mitchell + + * cp-tree.h (specializations_of_same_template_p): Declare. + * pt.c (specializations_of_same_template_p): New function. + (unify): Use it. + * search.c (get_template_base): Use it. + (get_template_base_recursive): Likewise. + +1998-10-10 Manfred Hollstein + + * decl2.c (start_objects): Add new variable `joiner' and + initialize it properly. + +1998-10-09 Mark Mitchell + + * search.c (expand_upcast_fixups): Tweak to match 1998-10-07 + change to vtable types. + + * cvt.c (ocp_convert): Avoid infinite recursion caused by + 1998-10-03 change. + +1998-10-08 Jason Merrill + + * pt.c (resolve_overloaded_unification): New fn. + (try_one_overload): Likewise. + (unify): Don't fail on unknown type. + (type_unification_real): Likewise. Use resolve_overloaded_unification + to handle an overloaded argument. + (template_args_equal): Split out... + (comp_template_args): From here. + (determine_specialization): Also allow a template with more + parms than were explicitly specified. + * cp-tree.h: Add template_args_equal. + * call.c (resolve_args): Remove TEMPLATE_ID_EXPR code. + +Thu Oct 8 15:58:30 1998 Anthony Green + + * semantics.c (finish_asm_stmt): Revert my 1998-09-28 + change. + +Thu Oct 8 06:00:19 1998 Jeffrey A Law (law@cygnus.com) + + * typeck.c (unsigned_type): Only return TItype nodes when + HOST_BITS_PER_WIDE_INT is >= 64 bits. + (signed_type): Likewise. + * decl.c (intTI_type_node, unsigned_intTI_type_node): Only declare + when HOST_BITS_PER_WIDE_INT is >= 64 bits. + (init_decl_processing): Only create TItype nodes when + HOST_BITS_PER_WIDE_INT is >= 64 bits. + * cp-tree.h (intTI_type_node, unsigned_intTI_type_node): Only declare + when HOST_BITS_PER_WIDE_INT is >= 64 bits. + +Wed Oct 7 12:32:44 1998 Kaveh R. Ghazi + + * Makefile.in (hash.h): Add -L KR-C -F ', 0, 0' flags to gperf. + (gxx.gperf): Update comments describing invocation flags. + (hash.h): Regenerate using gperf 2.7.1 (19981006 egcs). + +1998-10-07 Mark Mitchell + + * class.c (finish_struct_1): Add commentary on previous change. + + * cp-tree.h (vtbl_ptr_type_node): New variable. + * class.c (build_vtbl_ref): Don't indirect through the vptr; it's + already of the right type. + (finish_struct_1): Make the vptr be of type vtbl_ptr_type_node. + Simplify code to grow vtable. + * decl.c (vtbl_ptr_type_node): Define. + (init_decl_processing): Initialize it. + +1998-10-06 Mark Mitchell + + * cp-tree.def (PTRMEM_CST): New tree node. + * cp-tree.h (ptrmem_cst): New type. + (lang_type): Remove local_typedecls. + (dummy): Increase to 12 bits from 11. + (CLASSTYPE_LOCAL_TYPEDECLS): Remove. + (PTRMEM_CST_CLASS): New macro. + (PTRMEM_CST_MEMBER): Likewise. + (current_access_specifier): New variable. + (current_class_type): Remove duplicate declaration. + (finish_struct): Change prototype. + (unreverse_member_declarations): New function. + (pushdecl_class_level): Change prototype. + (grok_enum_decls): Remove. + (fixup_anonymous_union): New function. + (grok_x_components): Change prototype. + (tsubst_chain): Remove. + (finish_member_template_decl): Likewise. + (check_explicit_specialization): Fix indentation. + (finish_class_definition): Change prototype. + (finish_member_class_template): Likewise. + (finish_member_declaration): New function. + (check_multiple_declarators): Likewise. + * class.c (class_stack_node_t): New type. + (current_class_base): Remove. + (current_class_stack): Change type. + (current_access_specifier): New variable. + (grow_method): Remove. + (check_member_decl_is_same_in_complete_scope): Break out from + finish_struct. + (make_method_vec): New function. + (free_method_vec): Likewise. + (add_implicitly_declared_members): Break out from finish_struct_1. + (free_method_vecs): New variable. + (add_method): Rework for direct use from parser. + (handle_using_decl): Watch for NULL_TREE while iterating through + CLASSTYPE_METHOD_VEC. + (finish_struct_methods): Don't build CLASSTYPE_METHOD_VEC here; + just do some error-checking. + (warn_hidden): Change iteration through CLASSTYPE_METHOD_VEC. + (finish_struct_1): Simplify. Use add_implicitly_declared_members. + (finish_struct): Change prototype. Simplify; fields and methods + are already set up at this point. + (init_class_processing): Set up current_class_stack. + (pushclass): Save current_access_specifier. + (popclass): Restore it. + (currently_open_class): Simplify. + (build_self_reference): Remove use of CLASSTYPE_LOCAL_TYPEDECLS. + * decl.c (saved_scope): Add access_specifier. + (maybe_push_to_top_level): Save it. + (pop_from_top_level): Restore it. + (maybe_process_template_type_declaration): Use + finish_member_declaration. + (pushtag): Likewise. + (pushdecl_class_level): Don't return a value. + (fixup_anonymous_union): Break out from grok_x_components. + (shadow_tag): Use it. + (xref_tag): Complain about using an elaborated type specifier to + reference a template type parameter or typedef name. + (xref_basetypes): Don't set CLASSTYPE_LOCAL_TYPEDECLS. + (current_local_enum): Remove. + (build_enumerator): Call finish_member_declaration. + (grok_enum_decls): Remove. + * decl2.c (grok_x_components): Simplify. + (check_classfn): Change iteration through CLASSTYPE_METHOD_VEC. + (grokfield): Don't set CLASSTYPE_LOCAL_TYPEDECLS. + (merge_functions): Add to comment. + (arg_assoc_type): Prototype. + (arg_assoc): Pass as many arguments as there are parameters. + * error.c (dump_expr): Handle PTRMEM_CST. Improve handling of + OFFSET_REF. + * expr.c (cpls_expand_expr): Remove dead code. Handle + PTRMEM_CST. + * friend.c (do_friend): Lookup friends when in nested classes. + Change comments. + * init.c (build_offset_ref): Do lookup even for classes that are + only partially defined. + (decl_constant_value): Remove dead code. + * method.c (build_overload_value): Remove hack where by TYPE was + not a TYPE. Handle PTRMEM_CST. + (build_template_parm_names): Don't pass a PARM_DECL where a TYPE + should go. + * parse.y (components, notype_components, component_decl, + component_decl_1, component_declarator, component_declarator0): + Now all are itype rather than ttype. Rework to add members to + classes on the fly. + (typesqpecqual_reserved): Use check_multiple_declarators. + (structsp): Update class to finish_class_definition. + (do_xref_defn): Unsplit into named_class_head. + (access_specifier): Set current_access_specifier. + * pt.c (set_current_access_from_decl): New function. + (finish_member_template_decl): Don't take the parameters. + (comp_template_args): Make more robust. + (lookup_template_class): Don't use current_local_enum. + (for_each_template_parm): Handle PTRMEM_CST. + (instantiate_class_template): Use set_current_access_from_decl, + finish_member_declaration and unreverse_member_declarations. Set + lineno/input_filename before generating implicit member functions. + (type_unification_real): Don't assume back-unification happens + only for the last argument. + (regenerate_decl_from_template): Call pushclass a bit earlier. + (tsubst_chain): Remove. + (tsubst_enum): Use set_current_access_from_decl. + (set_mangled_name_for_template_decl): Fix indentation. + * search.c (lookup_fnfields_1): Change iteration through + CLASSTYPE_METHOD_VEC. + (dfs_pushdecls): Likewise. + (dfs_compress_decls): Likewise. + (add_conversions): Likewise. + * semantics.c (finish_class_definition): Don't take components. + Change call to finish_struct. + (finish_member_declaration): New function. + (finish_member_class_template): Don't take template parameters. + Change call to grok_x_components. Call finish_member_template_decl. + (check_multiple_declarators): New function. + * sig.c (append_signature_fields): Work from the TYPE_METHODS, not + a passed in fieldlist. + * tree.c (search_tree): Handle PTRMEM_CST. + (mapcar): Likewise. + * typeck.c (unary_complex_lvalue): Build PTRMEM_CSTs, not + INTEGER_CSTs, for pointer-to-data members. + + * call.c (resolve_args): Resolve template specializations, if + possible. + +Tue Oct 6 07:57:26 1998 Kaveh R. Ghazi + + * Makefile.in (spew.o): Depend on toplev.h. + + * call.c (compare_ics): Initialize variables `deref_from_type2', + `deref_to_type1' and `deref_to_type2'. + + * except.c (get_eh_type): Hide prototype and definition. + (process_start_catch_block_old): Remove unused static prototype. + + * pt.c (tsubst_decl): Initialize variable `argvec'. + + * spew.c: Include toplev.h. + +1998-10-05 Jason Merrill + + * pt.c (instantiate_decl): Do save and restore file position. + +1998-10-05 Martin von Löwis + + * method.c (build_decl_overload_real): Clear + numeric_output_need_bar after __. + +1998-10-05 Nathan Sidwell + + * call.c (build_new_method_call): Issue 'incomplete type' error, + if class is not defined. + +1998-10-05 Kaveh R. Ghazi + + * call.c (build_object_call): Move declaration of variable + `fn' into the scope where it is used. Don't access variable + `fn' when it is uninitialized, instead use `fns'. + +1998-10-04 Theodore Papadopoulo + + * errfn.c (cp_thing): Print buf as a string not as a printf format + to avoid problems with the operator%. Consequently, `%%' sequences + in format are copied as `%' in buf. + +1998-10-04 Jason Merrill + + * pt.c (pop_tinst_level): Call extract_interface_info. + (instantiate_decl): Don't save and restore file position. + + * decl.c (cp_finish_decl): Make statics in extern inlines and + templates common, if possible and the target doesn't support weak + symbols. + + * decl.c (grokdeclarator): Remove redundant calls to + build_type_variant and some duplicated code. + * sig.c (build_signature_reference_type): Only take the type parm. + (build_signature_pointer_type): Likewise. + * tree.c (build_cplus_method_type): Adjust. + * cp-tree.h: Update. + +1998-10-04 Mark Mitchell + + * call.c (build_over_call): Make pedwarns about dropped qualifiers + into full-fledged errors. + * cvt.c (convert_to_reference): Likewise. + * typeck.c (convert_for_assignment): Likewise. + + * search.c (expand_upcast_vtables): In addition to unsetting + TREE_READONLY, remove top-level const type qualifier. + +1998-10-03 Mark Mitchell + + * class.c (current_class_ptr, current_class_ref): Clarify + documentation. + * cvt.c (ocp_convert): Don't expect fold to remove all trivial + NOP type conversions. + * decl.c (decls_match): Use comptypes directly; ignore + qualifiers on the DECL. + (duplicate_decls): Remove qualifier checks on DECL. + (grokdeclarator): Make the type built up include top-level + qualifiers. + * decl2.c (do_dtors): Fix spelling error. + * error.c (dump_simple_decl): Don't look at qualifiers on the decl + when printing type information. + * init.c (build_new_1): Add documentation. Deal with the fact + that type of allocated memory now contains qualifiers. + * lex.c (is_global): Improve error-recovery. + * sig.c (build_member_function_pointer): Don't cast away const + on fields of sigtable_entry_type. + * tree.c (lvalue_type): Don't look at top-level qualifiers on + expressions. + * typeck.c (decay_conversion): Likewise. + (build_component_ref): Make sure the type of the COMPONENT_REF + contains top-level qualifiers, as appropriate. Improve + error-handling. + (build_indirect_ref): Simplify. Don't strip top-level qualifiers. + (build_array_ref): Likewise. + (build_unary_op): Improve error-recovery. + (unary_complex_lvalue): Make taking the address a bound member + function an error, not a sorry. + (build_conditional_expr): Look at the type qualifiers, not the + qualifiers on the expression itself. + +1998-10-03 Jason Merrill + + * decl2.c (merge_functions): Remove duplicates. + + * decl2.c: Add -f{no-,}implicit-inline-templates. + (import_export_decl): Check it. + + * decl.c (lookup_name_real): Template parms also take precedence + over implicit typename. Only warn if yylex. + + * typeck.c (build_conditional_expr): Only fold if ifexp is an + INTEGER_CST. + + * decl2.c (finish_vtable_vardecl): Check DECL_INTERFACE_KNOWN + instead of linkage. + +1998-10-01 Jason Merrill + + * cp-tree.h (FORMAT_VBASE_NAME): New macro. + * class.c (build_vbase_pointer): Use it. + * rtti.c (expand_class_desc): Likewise. + * tree.c (build_vbase_pointer_fields): Likewise. + +Thu Oct 1 10:43:45 1998 Nick Clifton + + * decl.c (start_decl): Add invocation of + SET_DEFAULT_DECL_ATTRIBUTES, if defined. + (start_function): Add invocation of + SET_DEFAULT_DECL_ATTRIBUTES, if defined. + + * lex.c: Replace occurrences of HANDLE_SYSV_PRAGMA with + HANDLE_GENERIC_PRAGMAS. + +1998-09-28 Anthony Green + + * semantics.c (finish_asm_stmt): Always permit volatile asms. + +1998-09-28 Mark Mitchell + + * decl.c (grokdeclarator): Tighten checks for invalid + destructors. Improve error-messages and error-recovery. + * decl2.c (check_classfn): Don't assume that mangled destructor + names contain type information. + +1998-09-25 Jason Merrill + + * search.c (get_base_distance): Remove assert. + + * decl2.c (build_anon_union_vars): Don't process a field with no + name. + (finish_anon_union): Also complain about local anon unions with no + members. + +1998-09-25 Martin von Löwis + + * decl.c (lookup_namespace_name): If the name is a namespace, + return it immediately. + +Fri Sep 25 11:45:38 1998 Kaveh R. Ghazi + + * cp-tree.h (define_case_label): Remove unused parameter. + (check_java_method): Likewise. + (grokclassfn): Likewise. + (expand_aggr_init): Likewise. + (build_x_delete): Likewise. + (maybe_end_member_template_processing): Likewise. + (unshare_base_binfos): Add prototype. + (string_conv_p): Likewise. + (my_friendly_abort): Mark with ATTRIBUTE_NORETURN. + + * cvt.c (build_up_reference): Remove unused parameter + `checkconst', all callers changed. + (build_type_conversion): Mark parameter `code' with + ATTRIBUTE_UNUSED. + (build_expr_type_conversion): Initialize variable `conv'. + + * decl.c (push_namespace): Initialize variable `d'. + (define_case_label): Remove unused parameter `decl', all callers + changed. + + * decl2.c (lang_decode_option): If !USE_CPPLIB, mark parameter + `argc' with ATTRIBUTE_UNUSED. + (grokclassfn): Remove unused parameter `cname', all callers + changed. + (check_java_method): Likewise for parameter `ctype'. + (copy_assignment_arg_p): Mark parameter `virtualp' with + ATTRIBUTE_UNUSED. + (finish_prevtable_vardecl): Likewise for parameter `prev'. + + * expr.c (extract_init): Likewise for parameters `decl' and `init'. + + * init.c (expand_aggr_init_1): Remove unused parameter + `alias_this', all callers changed. + (expand_aggr_init): Likewise. + (expand_default_init): Likewise. + (build_new_1): Initialize variable `susp'. + (build_x_delete): Remove unused parameter `type', all callers + changed. + + * lex.c (set_typedecl_interface_info): Mark parameter `prev' with + ATTRIBUTE_UNUSED. + (readescape): Use (unsigned) value in shift. + (real_yylex): Likewise. Likewise. Also cast `sizeof' to int when + comparing to a signed quantity. + + * pt.c (maybe_end_member_template_processing): Remove unused + parameter `decl', all callers changed. + (check_explicit_specialization): Add braces around empty body in + an else-statement. + (current_template_args): Initialize variable `args'. + (lookup_template_class): Likewise for variable `prev_local_enum'. + (tsubst_decl): Likewise for variable `r'. + (set_mangled_name_for_template_decl): Initialize variable + `context'. + + * spew.c (scan_tokens): Change type of parameter `n' to unsigned. + Likewise for variable `i'. + (yylex): Initialize variable `trrr'. + + * typeck.c (compparms): Mark variable `strict' with + ATTRIBUTE_UNUSED. + + * xref.c (simplify_type): Cast argument of ctype function to + `unsigned char'. + +1998-09-24 Mark Mitchell + + * cp-tree.h (language_lvalue_valid): Remove. + * decl.c (grokdeclarator): Don't disallow references to functions. + * tree.c (lvalue_p_1): New function, combining duplicated + code from ... + (lvalue_p): Use it. + (real_lvalue_p): Likewise. + * typeck.c (language_lvalue_valid): Remove. + (build_modify_expr): Treat FUNCTION_TYPEs as readonly, even though + they don't have TREE_READONLY set. + * typeck2.c (readonly_error): Add case for FUNCTION_DECLs. + +1998-09-24 Benjamin Kosnik + + * spew.c (yylex): Give diagnostic. + * hash.h (is_reserved_word): Add export. + * gxx.gperf: Likewise. + * lex.h (rid): Add RID_EXPORT. + * lex.c (init_parse): Likewise. + +Tue Sep 22 21:01:19 1998 Gerald Pfeifer + + * friend.c (do_friend): Make warning a full sentence. + +1998-09-22 Mark Mitchell + + * parse.y (component_decl_list): Improve error-recovery. + +1998-09-22 Benjamin Kosnik + + * decl.c (make_typename_type): Move error to point where name + variable can be used by dump_type. + +1998-09-22 Mark Mitchell + + * decl.c (grokfndecl): Improve error-recovery. + * decl2.c (grokfield): Likewise. + * pt.c (finish_member_template_decl): Likewise. + +1998-09-20 Martin von Löwis + + * method.c (hack_identifier): Finding multiple members is always + an error. + +1998-09-21 Per Bothner + + * Make-lang.in (c++-filt): Link libiberty.a after cxxmain.o. + +Mon Sep 21 01:53:05 1998 Felix Lee + + * lex.c (init_lex): Use getenv ("LANG"), not GET_ENVIRONMENT (). + +1998-09-20 Mark Mitchell + + * class.c (maybe_warn_about_overly_private_class): Reformat. + +1998-09-17 Andrew MacLeod + + * exception.cc (__cplus_type_matcher): Realign some code. + +1998-09-16 Mark Mitchell + + * Make-lang.in (tinfo.o): Use CXXFLAGS when compiling. + (tinfo2.o): Likewise. + (exception.o): Likewise. + (new.o): Likewise. + (opnew.o): Likewise. + (opnewnt.o): Likewise. + (opvnew.o): Likewise. + (opvnewnt.o): Likewise. + (opdel.o): Likewise. + (opdelnt.o): Likewise. + (opvdel.o): Likewise. + (opvdelnt.o): Likewise. + +1998-09-16 Richard Henderson + + * decl.c (init_decl_processing): Kill __builtin_fp and __builtin_sp. + +1998-09-15 Alexandre Oliva + + * call.c (build_field_call): Handle static data members too. + + * typeck.c (comptypes): When comparing pointer types, check + whether referred types match even in strictest modes. + +1998-09-15 Mark Mitchell + + * cp-tree.h: Revert previous change. + (finish_struct_methods): Remove declaration. + * class.c: Revert previous change. + (maybe_warn_about_overly_private_class): New function. + (finish_struct_methods): Declare here, and make static. Remove + unnecessary parameters. Tidy slightly. Use + maybe_warn_about_overly_private_class. + (finish_struct_1): Adjust. Remove check for private constructors, + now done elsewhere. + (finish_struct): Adjust. + +1998-09-15 Andrew MacLeod + + * except.c (expand_start_catch_block): No need to check for new + exception model. + (process_start_catch_block_old): Deleted. + (process_start_catch_block): Add call to start_decl_1(). + (expand_end_catch_block): Add call to end_catch_handler(). + * exception.cc (__cplus_type_matcher): Only check the exception + language if there is an exception table. + +1998-09-15 Andrew MacLeod + + * search.c (expand_indirect_vtbls_init): Mark temporary stack slots + as used to prevent conflicts with virtual function tables. + +1998-09-14 Mark Mitchell + + * cp-tree.h (lang_type): Add has_non_private_static_mem_fn. + (CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN): New macro, to access it. + * class.c (maybe_class_too_private_p): New function. + (finish_struct_methods): Use it. + (finish_struct_1): Likewise. + (finish_struct): Set CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN if + appropriate. + + * pt.c (check_specialization_scope): Fix spelling error. + (check_explicit_specialization): Remove code to handle explicit + specializations in class scope; they are now correctly diagnosed + as errors. + +1998-09-10 Mark Mitchell + + * decl.c (pushdecl): Don't copy types if the + DECL_ABSTRACT_ORIGIN of the new decl matches the TYPE_NAME of the + type. + +1998-09-09 Kriang Lerdsuwanakij + + * class.c (get_enclosing_class): New function. + (is_base_of_enclosing_class): Likewise. + * cp-tree.h (get_enclosing_class): Declare. + (is_base_of_enclosing_class): Likewise. + * pt.c (coerce_template_parms): Use them. + +1998-09-09 Jason Merrill + + * g++spec.c (lang_specific_driver): Check whether MATH_LIBRARY is + null to decide whether to use it. + + * error.c (dump_type_real): Handle NAMESPACE_DECL. + * parse.y (base_class.1): Avoid crash on error. + +1998-09-08 Martin von Löwis + + * decl.c (make_typename_type): If context is a namespace, the code + is in error. + +1998-09-08 Mumit Khan + + * parse.y (nomods_initdcl0): Set up the parser stack correctly. + +1998-09-08 Mark Mitchell + + * cp-tree.h (anonymous_namespace_name): Declare. + * decl.c: Define it. + (push_namespace): Use anonymous_namespace_name, rather than local + static anon_name. + * error.c (dump_decl): If a namespace is named + anonymous_namespace_name, call it {anonymous}. + + * decl.c (grokparms): Distinguish between references and pointers + in error message. + +1998-09-08 Richard Henderson + Mark Mitchell + + * pt.c (process_partial_specialization): Consistently allocate + and zero tpd.parms based on ntparms. Use tpd2.parms, not + tpd.parms, where appropriate. + +Sun Sep 6 00:00:51 1998 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (INCLUDES): Update after recent toplevel gcc + reorganizations. + +1998-09-05 Mark Mitchell + + * cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove. + * class.c (finish_struct): Remove hackery to deal with explicit + specializations in class scope. + * decl.c (grokfndecl): Improve error-recovery. + * decl2.c (grokfield): Likewise. + * pt.c (check_specialization_scope): New function. + (begin_specialization): Call it. + (process_partial_specialization): New function, split out from + push_template_decl. Check partial specializations more + stringently. + (push_template_decl): Call it. + (check_explicit_specialization): Don't attempt to handle explicit + specializations in class scope. + (template_parm_data): Document. Add current_arg and + arg_uses_template_parms. + (mark_template_parm): Set it. + (tsubst_arg_types): Remove unused variable. + * semantics.c (begin_class_definition): Tweak. + +1998-09-04 Mark Mitchell + + * inc/typeinfo (type_info::type_info(const char*)): Make + `explicit'. + + * cp-tree.h (hash_tree_cons_simple): New macro. + * pt.c (tsubst_arg_types): New function. Use hash_tree_cons. + (coerce_template_parms): Use make_temp_vec, instead of + make_tree_vec. Document this behavior. + (lookup_template_class): Likewise. + (tsubst, cases METHOD_TYPE, FUNCTION_TYPE): Use tsubst_arg_types. + Remove dead code (and add assertion to check its deadness). Fix + bug w.r.t. exception specifications. + +1998-09-03 Jason Merrill + + * decl2.c (import_export_vtable): Always make artificials comdat. + (import_export_decl): Likewise. + * pt.c (mark_decl_instantiated): Likewise. + +1998-09-03 Mark Mitchell + + * cp-tree.h (finish_globally_qualified_member_call_expr): + Rename to ... + (finish_qualified_call_expr). + * semantics.c: Likewise. + * parse.y (primary): Use it. + * method.c (hack_identifier): Remove redundant code. + + * init.c (resolve_offset_ref): Call convert_from_reference to + handle members of reference type. Improve error recovery. + +1998-09-03 Benjamin Kosnik + + * cp-tree.h: Declare warn_nontemplate_friend. + * decl2.c (lang_decode_option): Set. + * lang-options.h: Add -Wnon-template-friend. + * friend.c (do_friend): Use to toggle non-template function warning. + +1998-09-03 Mark Mitchell + + * decl.c (finish_enum): Don't resolve CONST_DECLs to their + corresponding INTEGER_CSTs when processing_template_decl. + * pt.c (tsubst_enum): Tweak accordingly. + +1998-09-03 Benjamin Kosnik + + * decl.c (pushdecl_class_level): Add warning here. + (pushdecl): Tweak. + +1998-09-02 Jason Merrill + + * cvt.c (convert_pointer_to_real): Tidy. + * search.c (get_base_distance_recursive): Simplify. + (get_base_distance): Likewise. + + * pt.c (unify): Only special-case INTEGER_TYPE if it uses template + parms. + +Wed Sep 02 09:25:29 1998 Nick Clifton + + * lex.c (check_newline): Call HANDLE_PRAGMA before + HANDLE_SYSV_PRAGMA if both are defined. Generate warning messages + if unknown pragmas are encountered. + (handle_sysv_pragma): Interpret return code from + handle_pragma_token (). Return success/failure indication rather + than next unprocessed character. + (pragma_getc): New function: retrieves characters from the + input stream. Defined when HANDLE_PRAGMA is defined. + (pragma_ungetc): New function: replaces characters back into the + input stream. Defined when HANDLE_PRAGMA is defined. + +1998-09-01 Jason Merrill + + * decl2.c (output_vtable_inherit): Use %cDIGIT in the operands. + * class.c (build_vtable_entry_ref): Likewise. + +1998-09-01 Mark Mitchell + + * cp-tree.h (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION): New macro. + * decl2.c (import_export_decl): Likewise. + * pt.c (instantiate_decl): Use it. + +1998-09-01 Jason Merrill + + * decl.c (lookup_name_real): Also do implicit typename thing for + artificial TYPE_DECLs. + * search.c (lookup_field): Likewise. + (lookup_fnfields, lookup_field): Adjust for implicit typename kludge. + * semantics.c (begin_constructor_declarator): Use enter_scope_of. + (enter_scope_of): Extract type from implicit typename. + (begin_class_definition): Likewise. + * lex.c (identifier_type): Handle implicit typename when checking + for SELFNAME. + + * cp-tree.h: Declare flag_strict_prototype. + * lex.c (do_scoped_id, do_identifier): Don't implicitly_declare if + -fstrict-prototype. + * decl.c (init_decl_processing): If -f{no,-}strict-prototype wasn't + specified, set it to the value of pedantic. + +1998-09-01 Mark Mitchell + + * decl2.c (arg_assoc): Handle template-id expressions as arguments. + +1998-08-31 Mark Mitchell + + * decl.c (finish_enum): Handle member enums of classes declared in + template functions. + + * decl2.c (grok_x_components): Strip attributes before calling + groktypename. + +1998-08-31 Jason Merrill + + * cp-tree.h, decl2.c: Remove support for -fall-virtual, + -fenum-int-equivalence and -fno-nonnull-objects. + * class.c (check_for_override): Remove support for -fall-virtual. + (finish_struct_1): Likewise. + * call.c (build_new_op): Remove support for -fenum-int-equivalence. + * typeck.c (build_binary_op_nodefault): Likewise. + * cvt.c (ocp_convert): Likewise. + * call.c (build_vfield_ref): Remove support for -fno-nonnull-objects. + * class.c (build_vbase_path): Likewise. + +Sun Aug 30 22:16:31 1998 H.J. Lu (hjl@gnu.org) + + * Makefile.in (INTERFACE): New, set to 1. + +1998-08-30 Mark Mitchell + + * error.c (dump_decl): Use CP_DECL_CONTEXT, not DECL_CONTEXT, when + comparing with global_namespace. + (dump_aggr_type): Likewise. + + * decl.c (grokfndecl): Issue error on declaration of friend + templates with explicit template arguments. + + * pt.c (convert_template_argument): New function, split out + from... + (coerce_template_parms): Here. + (tsubst): Attempt better error-recovery. + +1998-08-28 Benjamin Kosnik + + * pt.c (decl_template_parm_p): Add checks for + TEMPLATE_TEMPLATE_PARM. + +1998-08-28 Mark Mitchell + + * lex.c (do_identifier): Fix thinko in previous change. + +1998-08-28 Jason Merrill + + * search.c (dfs_search, binfo_for_vtable, dfs_bfv_helper): New fns. + * decl2.c (output_vtable_inherit): Call binfo_for_vtable. + +1998-08-28 Richard Henderson + + Add support for discarding unused virtual functions. + * lang-options.h: Add -fvtable-gc. + * cp-tree.h: Add flag_vtable_gc. + * decl2.c (output_vtable_inherit): New fn. + (finish_vtable_vardecl): Call it. + * class.c (build_vtable_entry_ref): New fn. + (build_vtbl_ref): Call it. + +1998-08-28 Mark Mitchell + + * cp-tree.h (build_enumerator): Take the enumeration type as a + parameter. + * decl.c (finish_enum): Don't set the TREE_TYPE for the + enumeration constant values if we're processing_template_decls. + Don't set the type for the CONST_DECLs either; that's done in + build_enumerator. + (build_enumerator): Take the enumeration type as a + parameter. + * lex.c (do_identifier): Don't resolve enumeration constants while + processing template declarations, even if they happen to be + TEMPLATE_PARM_INDEXs. + + * parse.y (current_enum_type): New variable. + (primary): Don't allow statement-expression in local classes just + as we don't in global classes. + (structsp): Use current_enum_type. + (enum_list): Likewise. + * pt.c (tsubst_enum): Don't check for NOP_EXPRs introduced by + finish_enum; they no longer occur. + + * cp-tree.h (finish_base_specifier): New function. + * parse.y (base_class): Use it. + * semantics.c (finish_base_specifier): Define it. + + * parse.y (structsp): Warn on use of typename outside of template + declarations. + +1998-08-27 Jason Merrill + + * lex.c (handle_cp_pragma): Remove #pragma vtable. + * lang-options.h: Remove +e options. + * decl2.c (lang_decode_option): Likewise. + (import_export_vtable): Don't check write_virtuals. + (finish_vtable_vardecl, finish_file): Likewise. + * search.c (dfs_debug_mark): Likewise. + * semantics.c (begin_class_definition): Likewise. + * class.c (build_vtable, finish_vtbls, finish_struct_1): Likewise. + + * call.c (build_over_call): Check flag_elide_constructors. + * decl2.c: flag_elide_constructors defaults to 1. + * typeck.c (convert_arguments): Remove return_loc parm. + (build_function_call_real): Adjust. + + * search.c: Tear out all mi_matrix and memoize code. + (lookup_field, lookup_fnfields): Use scratch_tree_cons. + * lang-options.h: Remove documentation for -fhandle-exceptions, + -fmemoize-lookups and -fsave-memoized. + * cp-tree.h: Lose mi_matrix and memoize support. + * decl2.c: Ignore -fmemoize-lookups and -fsave-memoized. + * class.c: Lose struct class_level. + (pushclass, popclass): Lose memoize support. + * init.c (build_offset_ref): Likewise. + + Never change BINFO_INHERITANCE_CHAIN. + * init.c (emit_base_init): Change modification of + BINFO_INHERITANCE_CHAIN to an assert. + * search.c (get_base_distance_recursive): Likewise. + (get_base_distance): Likewise. + (lookup_member): Likewise. + (convert_pointer_to_single_level): Likewise. + (lookup_field): Likewise. Lose setting TREE_VIA_* on TREE_LISTs. + (lookup_fnfields): Likewise. + * tree.c (propagate_binfo_offsets): Don't call unshare_base_binfos. + (unshare_base_binfos): Don't call propagate_binfo_offsets. + (layout_basetypes): Call propagate_binfo_offsets instead of + unshare_base_binfos. + * decl.c (xref_basetypes): Call unshare_base_binfos. + * pt.c (instantiate_class_template): Likewise. + * tree.c (reverse_path): Remove 'copy' parm; always make a + temporary copy. + * class.c (build_vbase_path): Just call it. + * search.c (compute_access): Likewise. Don't re-reverse. + +1998-08-27 Mark Mitchell + + * class.c (build_vbase_path): Use reverse_path. + (finish_base_struct): Move warnings for inaccessible bases to + layout_basetypes. + (modify_one_vtable): Remove check of TREE_USED (binfo). + (fixup_vtable_deltas1): Likewise. + * cp-tree.h (BINFO_INHERITANCE_CHAIN): Document here. + (xref_tag): Remove binfos parameter. + (make_binfo): Remove chain parameter. + (reverse_path): Add copy parameter. + * decl.c (init_decl_processing): Change calls to xref_tag. + (xref_tag): Remove binfos parameter. + (xref_basetypes): Change calls to make_binfo. + * decl2.c (grok_x_components): Change calls to xref_tag. + (handle_class_head): Likewise. + * friend.c (do_friend): Likewise. + * lex.c (make_lang_type): Change calls to make_binfo. + * parse.y (structsp): Change calls to xref_tag. + (named_complex_class_head_sans_basetype): Likewise. + (named_class_head): Likewise. + * rtti.c (init_rtti_processing): Likewise. + * search.c (compute_access): Change calls to reverse_path. + (dfs_get_vbase_types): Change calls to make_binfo. + (get_vbase_types): Remove dead code. + * tree.c (unshare_base_binfos): Change calls to make_binfo. + (layout_basetypes): Warn here about inaccessible bases. + (make_binfo): Remove chain parameter. + (reverse_path): Add copy parameter. + +1998-08-27 Jason Merrill + + * class.c: #if 0 complete_type_p. + * init.c (build_java_class_ref, build_new_1): Remove unused locals. + * method.c (process_overload_item): Likewise. + * typeck.c (comp_target_types): Likewise. + + Stop sharing binfos for indirect virtual bases. + * tree.c (propagate_binfo_offsets): Unshare vbases, too. + (layout_basetypes): Likewise. + (unshare_base_binfos): Copy vbases, too. + * cp-tree.h (BINFO_VIA_PUBLIC, BINFO_BASEINIT_MARKED, + BINFO_VBASE_INIT_MARKED): Remove obsolete macros. + (BINFO_PUSHDECLS_MARKED, SET_BINFO_PUSHDECLS_MARKED, + CLEAR_BINFO_PUSHDECLS_MARKED): New macros. + * search.c (lookup_field, lookup_fnfields, lookup_member): Remove + reference to BINFO_VIA_PUBLIC. + (marked_pushdecls_p, unmarked_pushdecls_p): New fns. + (push_class_decls): Use them. + (dfs_pushdecls): Use SET_BINFO_PUSHDECLS_MARKED. + (dfs_compress_decls): Use CLEAR_BINFO_PUSHDECLS_MARKED. + +1998-08-27 Mark Mitchell + + * decl.c (build_enumerator): Set DECL_CONTEXT for the + CONST_DECLs. + +1998-08-26 Mark Mitchell + + * cp-tree.h (finish_enum): Change prototype. + * decl.c (finish_enum): Use TYPE_VALUES, rather than taking a + VALUES parameter. Don't try to compute mins/maxs if + processing_template_decl. + * parse.y (structsp): Use new calling sequence for finish_enum. + * pt.c (tsubst_enum): Likewise. Take the new type as input. + (lookup_template_class): Remove unused variables. Tweak. + Register enums on instantiation list before substituting + enumeration constants. + (tsubst_decl): Remove unused variables. + (regenerate_decl_from_template): Likewise. + + * decl.c (duplicate_decls): Don't obliterate the + DECL_TEMPLATE_INFO for a template if we're not replacing it with + anything. + + * lex.c (do_identifier): Fix typo in comment. + +Wed Aug 26 10:54:51 1998 Kaveh R. Ghazi + + * errfn.c: Remove stdarg.h/varargs.h. + * tree.c: Likewise. + +1998-08-25 Brendan Kehoe + + * pt.c (tsubst_copy): Only do typename overloading on an + IDENTIFIER_NODE that happens to look like a typename if it actually + has a type for us to use. + +1998-08-25 Jason Merrill + + * typeck.c (comp_cv_target_types): Split out... + (comp_target_types): From here. Don't allow cv-qual changes under + a pointer if nptrs == 0. Fix OFFSET_TYPE handling. + (build_ptrmemfunc): Pass 1 to nptrs. + * cvt.c (perform_qualification_conversions): Use comp_ptr_ttypes. + +1998-08-25 Mark Mitchell + + * search.c (dependent_base_p): Don't compare a binfo to + current_class_type; use the TREE_TYPE of the binfo instead. + + * cp-tree.h (CLASS_TYPE_P): Revise definition. + +1998-08-25 Jason Merrill + + * decl.c (duplicate_decls): Don't complain about different + exceptions from an internal decl even if pedantic. + + * typeck.c (convert_for_assignment): Converting from pm of vbase + to derived is an error, not a sorry. + + * call.c (build_over_call): Use convert_pointer_to_real for 'this'. + * class.c (fixed_type_or_null): Rename from + resolves_to_fixed_type_p. Return the dynamic type of the + expression, if fixed, or null. + (resolves_to_fixed_type_p): Use it. Return 0 if the dynamic type + does not match the static type. + (build_vbase_path): Rename 'alias_this' to 'nonnull'. Use + resolves_to_fixed_type_p again. + +1998-08-24 Mark Mitchell + + * pt.c (tsubst_decl): Move special case code for dealing with + tricky friend templates here from ... + (regenerate_decl_from_template): Here. + +1998-08-24 Jason Merrill + + * decl.c (start_decl): Remove redundant linkage check. + +1998-08-24 Gavin Romig-Koch + + * typeck.c (c_expand_return): Handle the case that valtype + is wider than the functions return type. + +1998-08-24 Mark Mitchell + + * cp-tree.h (CLASS_TYPE_P): New macro. + * decl.c (grokdeclarator): Use it instead of IS_AGGR_TYPE. + * pt.c (process_template_parm): Undo previous change. + +1998-08-24 Benjamin Kosnik + + * cp-tree.h: Declare. + * pt.c (decl_template_parm_p): New function. + * decl.c (pushdecl): Check decls for redeclaring template parms. + (xref_tag): Make redeclaration an error, print decl. + * decl2.c (grokfield): Check field_decls for redeclaration as well. + +1998-08-24 Jason Merrill + + * parse.y (primary): Fix up the type of string constants. + +1998-08-24 Mark Mitchell + + * typeck.c (convert_for_initialization): Move check for odd uses + of NULL to avoid duplicate warnings. + +1998-08-24 Jason Merrill + + * tree.c (lvalue_type): Fix for arrays. + * typeck.c (string_conv_p): New fn. + (convert_for_assignment): Use it. + (build_unary_op): Use lvalue_type. + * call.c (standard_conversion, convert_like): Use string_conv_p. + (add_function_candidate): Use lvalue_type. + * cvt.c (convert_to_reference): Likewise. + * decl2.c (lang_decode_option): Ignore -traditional. + * decl.c (init_decl_processing): flag_writable_strings inhibits + flag_const_strings. + +1998-08-24 Andrew MacLeod + + * lang-options.h (lang_options): Add fconst-strings to the list + of valid options. + * decl2.c (lang_f_options, lang_decode_option): Likewise. + +1998-08-24 Nathan Sidwell + + * lex.c (real_yylex): Don't warn about long long constants if + we're allowing long long. + +1998-08-24 Martin von Löwis + + * decl.c (pushdecl): Use IDENTIFIER_NAMESPACE_VALUE instead of + accessing bindings directly. + + * search.c (my_tree_cons): Reimplement. + + * lang-specs.h: Remove __HONOR_STD. + * inc/exception, inc/new, inc/new.h, inc/typeinfo: Likewise. + +1998-08-23 Mark Mitchell + + * decl.c (grokdeclarator): Complain about in-class initialization + of aggregates and/or references. + * pt.c (process_template_parm): Clear IS_AGGR_TYPE for + TEMPLATE_TYPE_PARMs. + + * decl2.c (grok_array_decl): Add comment. + (mark_used): Don't instantiate an explicit instantiation. + * friend.c (make_friend_class): Remove bogus comment. Fix check + for partial specializations. + * pt.c (check_explicit_specialization): Don't + SET_DECL_EXPLICIT_INSTANTIATION here. + (mark_decl_instantiated): Or here. + (do_decl_instantiation): Do it here, instead. Add checks for + duplicate explicit instantiations, etc. Tidy. + (do_type_instantiation): Likewise. + (instantiate_decl): Improve comments. Complain about explicit + instantiations where no definition is available. + + * cp-tree.h (ansi_null_node): Remove. + * call.c (build_over_call): Warn about converting NULL to an + arithmetic type. + * cvt.c (build_expr_type_conversion): Likewise. Use + null_ptr_cst_p instead of expanding it inline. + * decl.c (ansi_null_node): Remove. + (init_decl_processing): Make null_node always have integral type. + * except.c (build_throw): Warn about converting NULL to an + arithmetic type. + * lex.c (init_parse): Remove handling of ansi_null_node. + * pt.c (type_unification_real): Don't convert NULL to void* type. + * typeck.c (build_binary_op_nodefault): Fix NULL warnings. + (convert_for_assignment): Warn about converting NULL to an + arithmetic type. + (convert_for_initialization): Likewise. + +1998-08-20 Jason Merrill + + * tree.c (search_tree, no_linkage_helper, no_linkage_check): New fn. + * pt.c (coerce_template_parms): Use no_linkage_check. + * decl.c (grokvardecl): Likewise. + (grokfndecl): Likewise. Members of anonymous types have no linkage. + + * method.c (process_overload_item): Remove useless code. + +1998-08-20 Per Bothner + + Handle new'ing of Java classes. + * init.c (build_class_classref): New function. + (build_new_1): If type is TYPE_FOR_JAVA: Call _Jv_AllocObject; + constructor does not return this; don't need to exception-protect. + + * pt.c (lookup_template_class): Copy TYPE_FOR_JAVA flag. + * decl2.c (acceptable_java_type): Handle template-derived types. + +1998-08-20 Per Bothner + + * decl2.c (import_export_vtable): Suppress vtables for Java classes. + +1998-08-20 Mark Mitchell + + * decl.c (duplicate_decls): Always merge the old and new patterns + for templates, regardless of whether or not the new one has + DECL_INITIAL. Don't throw away specializations. Merge + DECL_SAVED_TREE. + * pt.c (tsubst_decl): Use the right pattern when calculating the + complete args for a new template instance. + (do_decl_instantiation): Fix typo in comment. + (regenerate_decl_from_template): Deal with tricky friend template + case. + (instantiate_decl): Likewise. + +Thu Aug 20 09:09:45 1998 Jeffrey A Law (law@cygnus.com) + + * init.c (build_builtin_delete_call): Add missing assemble_external + call. + +1998-08-20 Jason Merrill + + * parse.y (notype_unqualified_id): Also accept ~A. + +1998-08-19 Mark Mitchell + + * typeck.c (build_binary_op_nodefault): Warn on use of NULL in + arithmetic. + * except.c (build_throw): Warn when NULL is thrown, even with + -ansi. Use ansi_null_node, rather than integer_zero_node, in the + thrown expression. + + * cp-tree.h (ansi_null_node): New variable. + * decl.c (ansi_null_node): New variable. + (init_decl_processing): Initialize its type. + * lex.c (init_parse): Initialize its value. Use ansi_null_node + for null_node in non-ANSI mode. + * typeck.c (build_binary_op_nodefault): Use ansi_null_node in + place of null_node to avoid spurious errors. + +1998-08-17 Mark Mitchell + + * cp-tree.h (enter_scope_of): New function. + * parse.y (complex_direct_notype_declarator): Use it. + * semantics.c (enter_scope_of): New function. + +1998-08-17 Jason Merrill + + * decl.c (grokparms): No, here. + + * decl.c (grokdeclarator): Catch parm with pointer to array of + unknown bound here... + * method.c (process_overload_item): ...not here. + + * gxxint.texi: Remove obsolete documentation of overloading code. + + * decl.c (finish_enum): Also set TYPE_SIZE_UNIT. + * class.c (finish_struct_bits): Likewise. + + * tree.c (lvalue_type): Fix for arrays. + * typeck.c (build_unary_op): Use lvalue_type. + * call.c (add_function_candidate): Likewise. + * cvt.c (convert_to_reference): Likewise. + + * decl2.c (lang_decode_option): Ignore -traditional. + + * init.c (build_offset_ref): Don't mess with error_mark_node. + * lex.c (do_scoped_id): Use cp_error. + + * rtti.c (get_tinfo_fn): Don't mess with the context for now. + +1998-08-17 Benjamin Kosnik + + * decl.c (grokdeclarator): Allow anonymous types to be cv-qualified. + +Mon Aug 17 10:40:18 1998 Jeffrey A Law (law@cygnus.com) + + * cp-tree.h (set_identifier_local_value): Provide prototype. + + * decl2.c (do_namespace_alias): Remove unused variables `binding' + and `old'. + +Fri Aug 14 16:42:27 1998 Nick Clifton + + * Makefile.in: Rename BBISON to BISON so that it can be properly + inherited from the parent makefile. + +1998-08-13 Jason Merrill + + * lang-options.h: Add -finit-priority. + * decl2.c: Likewise. Check flag_init_priority instead of + USE_INIT_PRIORITY. + + * decl2.c (setup_initp): New fn. + (start_objects, finish_objects, do_ctors): Handle init_priority. + (do_dtors, finish_file): Likewise. + +1998-08-13 Jason Merrill + + * pt.c (tsubst_copy): Hush warning. + + * rtti.c (get_tinfo_fn): Also set DECL_IGNORED_P. + +1998-08-12 Mark Mitchell + + * pt.c (print_template_context): Don't abort when instantiating a + synthesized method. + + * decl.c (grokdeclarator): Issue errors on namespace qualified + declarators in parameter lists or in class scope. + +1998-08-09 Mark Mitchell + + * pt.c (check_explicit_specialization): Don't abort on bogus + explicit instantiations. + +1998-08-07 Mark Mitchell + + * typeck.c (require_complete_type): Use complete_type_or_else. + (complete_type_or_else): Always return NULL_TREE on failure, as + documented. + + * pt.c (tsubst_aggr_type): Prototype. + (tsubst_decl): New function, split out from tsubst. Set + input_filename and lineno as appropriate. + (pop_tinst_level): Restore the file and line number saved in + push_tinst_level. + (instantiate_class_template): Set input_filename and lineno as + appropriate. + (tsubst): Move _DECL processing to tsubst_decl. Make sure the + context for a TYPENAME_TYPE is complete. + + * decl2.c (grokbitfield): Issue errors on bitfields declared with + function type. + (do_dtors): As in do_ctors, pretend to be a member of the same + class as a static data member while generating a call to its + destructor. + + * cvt.c (cp_convert_to_pointer): Handle NULL pointer + conversions, even in complex virtual base class hierarchies. + +1998-08-06 Mark Mitchell + + * cp-tree.h (ENUM_TEMPLATE_INFO): New macro. + (TYPE_TEMPLATE_INFO): Likewise. + (SET_TYPE_TEMPLATE_INFO): Likewise. + (ENUM_TI_TEMPLATE): Likewise. + (ENUM_TI_ARGS): Likewise. + (lookup_nested_type_by_name): Remove. + * decl.c (maybe_process_template_type_declaration): Handle enums. + (start_enum): Don't check for primary-template enum declarations + here. + (finish_enum): Clean up, document. Make sure template enum + constants get the correct type. + (build_enumerator): Copy initializers for template enumerations, + too. + (grok_enum_decls): Document. + * lex.c (do_identifier): Document use of LOOKUP_EXPR a bit + better. Build LOOKUP_EXPRs for local variables, even if they are + TREE_PERMANENT. + * pt.c (tsubst_enum): Remove field_chain parameter. + (template_class_depth): Include the depth of surrounding function + contexts. + (push_template_decl): Check for primary-template enum declarations + here. Deal with enumeration templates. + (lookup_template_class): Likewise. + (for_each_template_parm): Likewise. + (instantiate_class_template): Don't call tsubst_enum directly, + call tsubst instead, to instantiate enums. Deal with all + field_chain issues here, not in tsubst_enum. + (lookup_nested_type_by_name): Remove. + (tsubst_aggr_type): Revise handling of enumeration types. + (tsubst): Likewise. + (tsubst_copy): Likewise. + (tsubst_expr): Call tsubst, not tsubst_enum for TAG_DEFNs. + +1998-08-04 Mark Mitchell + + * decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it + uses template parameters. + * method.c (build_template_parm_names): Use the full set of + template arguments for tsubst'ing. + (build_overload_identifier): Pass the full set of template + arguments to build_template_parm_names, not just the + innermost_args. + * pt.c (TMPL_ARGS_DEPTH): Define using + TMPL_ARGS_HAVE_MULTIPLE_LEVELS, for clarity. + (NUM_TMPL_ARGS): New macro. + (add_outermost_template_args): Deal with the case where the outer + args will be completely discarded. + (coerce_template_parms): Use the full set of template arguments + for tsubst'ing. Simplify. Add some asserts. Improve + error messages. + (lookup_template_class): Pass the full set of template arguments + to coerce_template_parms. + (tsubst): Add assertion. + (do_type_instantiation): Don't instantiate member template + classes. + + * init.c (build_offset_ref): Deal with a TEMPLATE_ID_EXPR whose + name is a LOOKUP_EXPR, rather than an IDENTIFIER_NODE. + +1998-08-03 Jason Merrill + + * method.c (set_mangled_name_for_decl): Change return type to void. + + * decl.c (lookup_name_real): A namespace-level decl takes priority + over implicit typename. Avoid doing the same lookup twice. + + * search.c (dependent_base_p): New fn. + (dfs_pushdecls, dfs_compress_decls): Use it. + + * typeck.c (get_member_function_from_ptrfunc): Don't try to handle + virtual functions if the type doesn't have any. + +1998-08-03 Mark Mitchell + + * decl2.c (grokfield): Don't mangle the name of a TYPE_DECL if it + uses template parameters. + +1998-08-02 Mark Mitchell + + * cp-tree.def (LOOKUP_EXPR): Document. Remove second argument. + * cp-tree.h (DECL_TI_TEMPLATE): Improve documentation. + * lex.c (do_identifier): Don't use a second argument, or a type, + when building LOOKUP_EXPRs. + (do_identifier): Likewise. + (do_scoped_id): Likewise. + * method.c (hack_identifier): Improve error message. + * pt.c (lookup_template_function): Don't needlessly call + copy_to_permanent or build_min. + (tsubst_copy): Remove #if 0'd code. tsubst into LOOKUP_EXPRs if + necessary. + (do_decl_instantiation): Improve error message. + * tree.c (mapcar, case LOOKUP_EXPR): Don't be sorry; make a copy. + (build_min): Copy the type to the permanent obstack, too. + +1998-08-01 Jason Merrill + + * init.c (init_init_processing): Remove BI* handling. + (build_builtin_call): Remove. + (build_builtin_delete_call): New fn. + (build_delete): Use it. + +1998-07-31 Mark Mitchell + + * cp-tree.h (PROCESSING_REAL_TEMPLATE_DECL_P): New macro. + (maybe_check_template_type): New function. + * decl.c (maybe_process_template_type_declaration): New function, + split out from pushtag Call maybe_check_template_type. + (pushtag): Use it. Use PROCESSING_REAL_TEMPLATE_DECL_P. + (xref_tag): Use PROCESSING_REAL_TEMPLATE_DECL_P. + * friend.c (do_friend): Use PROCESSING_REAL_TEMPLATE_DECL_P. + * pt.c (template_class_depth_real): Generalization of ... + (template_class_depth): Use it. + (register_specialization): Use duplicate_decls for duplicate + declarations of specializations. + (maybe_check_template_type): New function. + (push_template_decl_real): Fix comment. + (convert_nontype_argument): Likewise. + (lookup_template_class): Likewise. Avoid an infinite loop on + erroneous code. + (tsubst_friend_function): Fix comment. + (tsubst, case FUNCTION_DECL): Deal with a DECL_TI_TEMPLATE that is + an IDENTIFIER_NODE. + * semantics.c (begin_function_definition): Use + reset_specialization to note that template headers don't apply + directly to declarations after the opening curly for a function. + +1998-07-29 Jason Merrill + + * decl.c (push_overloaded_decl): Use current_namespace instead of + DECL_CONTEXT (decl) to determine where we go. + + * decl.c (lookup_name_real): Fix typo. + +1998-07-28 Mark Mitchell + + * friend.c (is_friend): Be lenient with member functions to deal + with nested friends. + +1998-07-28 Jason Merrill + + * class.c (finish_struct_1): Convert integer_zero_node to + ssizetype before passing it to set_rtti_entry. + * typeck2.c (initializer_constant_valid_p): Allow conversion of 0 + of any size to a pointer. + +1998-07-27 Mark Mitchell + + * cp-tree.h (TI_USES_TEMPLATE_PARMS): Remove. + (build_template_decl_overload): Remove. + (set_mangled_name_for_decl): New function. + (innermost_args): Remove is_spec parameter. + (most_specialized, most_specialized_class): Remove declarations. + (lookup_template_class): Add entering_scope parameter. + (maybe_process_partial_specialization): New function. + (finish_template_decl): Likewise. + (finish_template_type): Likewise. + * class.c (finish_struct): Clean up processing of member template + specializations. + * decl.c (pushtag): Fix formatting. + (lookup_tag): Improve handling of pseudo-global levels. + (make_typename_type): Adjust call to lookup_template_class. + (shadow_tag): Use maybe_process_partial_specialization. + (xref_tag): Improve handling of member friends. + (start_function): Call push_nested_class before + push_template_decl. Don't call push_template_decl for + specializations. + * decl2.c (grok_x_components): Don't call xref_tag for + template instantiations. Handle UNION_TYPEs like RECORD_TYPEs. + (grokclassfn): Use set_mangled_name_for_decl. + (arg_assoc_class): Adjust call to innermost_args. + (mark_used): Don't call instantiate_decl for a TEMPLATE_DECL. + * error.c (dump_function_name): Improve printing of template + function names. + * friend.c (is_friend): Don't compare types of decls to determine + friendship, unless flag_guiding_decls. + (make_friend_class): Partial specializations cannot be friends. + (do_friend): Use set_mangled_name_for_decl. Call + push_template_decl_real instead of push_template_decl. + * method.c (build_decl_overload_real): Remove prototype. Give it + external linkage. + (build_overload_identififer): Adjust call to innermost_args. + (build_template_decl_overload): Remove. + (set_mangled_name_for_decl): New function. + * parse.y (.finish_template_type): New non-terminal. + (template_def): Use finish_template_decl. Use template_extdef + instead of extdef. + (template_extdef, template_datadef): New non-terminals, containing + only those rules for things which can be templates. + (datadef): Tidy. + (template_type, self_template_type): Use .finish_template_type. + (named_class_head): Use maybe_process_partial_specialization. + * pt.c (mangle_class_name_for_template): Remove context parameter. + (get_class_bindings): Remove outer_args parameter. + (complete_template_args): Remove. + (add_outermost_template_args): New function. + (register_specialization): Return the specialization. + (unregister_specialization): New function. + (tsubst_template_parms): Likewise. + (most_specialized, most_specialized_class): Prototype here as + static. + (original_template): Rename to most_general_template. + (tsubst_template_parms): New function. + (set_mangled_name_for_template_decl): Likewise. + (TMPL_ARGS_DEPTH): New macro. + (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Adjust. + (TMPL_ARGS_LEVEL): New macro. + (SET_TMPL_ARGS_LEVEL): Likewise. + (TMPL_ARG): Likewise. + (SET_TMPL_ARG): Likewise. + (TMPL_ARGS_DEPTH): Likewise. + (finish_member_template_decl): Use finish_template_decl. + (maybe_process_partial_specialization): New function, split out + from tsubst. + (inline_needs_template_parms): Use TMPL_PARMS_DEPTH. + (maybe_begin_member_template_processing): Use new macros. + (is_member_template): Likewise. + (is_member_template_class): Likewise. + (add_to_template_args): Likewise. Deal with multiple levels of + args. + (maybe_process_partial_specialization): New function. + (retrieve_specialization): Add consistency check. + (determine_specialization): Return full argument list. + (check_explicit_specialization): Tweak friend handling. Use full + argument lists. Simplify. + (current_template_args): Use new macros. + (push_template_decl_real): Change ill-named mainargs to specargs. + Check that a partial specialization actually specializes at least + one parameter. Improve friend handling. Modify for full + template arguments. + (classtype_mangled_name): Don't mangle the names of + specializations. + (lookup_template_class): Add entering_scope parameter. Use it to + avoid finding a template type when an instantiation is required. + Simplify. Use full template arguments. + (tsubst_friend_function): Use unregister_specialization. Use new + macros. Use full template arguments. + (tsubst_friend_class): Substitute, using tsubst_template_parms, + into the template parameters before passing them to + redeclare_class_template. + (instantiate_class_template): Simplify. Use full template + arguments. Adjust calls to get_class_bindings. Use + SET_IDENTIFIER_TYPE_VALUE where needed. Improve friend handling. + (innermost_args): Use new macros. + (tsubst_aggr_type): New function, split out from tsubst. + (tsubst): Use tsubst_aggr_type, tsubst_template_parms, new calling + conventions for lookup_template_class. Refine handling of partial + instantiations. Remove calls to complete_template_args. + Simplify. Add consistency checks. Use set_mangled_name_for_decl + and set_mangled_name_for_template_decl. + (tsubst_copy): Use tsubst_aggr_type. + (instantiate_template): Use full template arguments. + (more_specialized): Improve formatting. + (more_specialized_class): Adjust calls to get_class_bindings. + (get_bindings_real): Don't call complete_template_args. + (most_specialized): Don't overwrite input; create a new list. + (most_specialized_class): Use most_general_template. + (regenerate_decl_from_template): Use unregister_specialization. + Use full template arguments. + (instantiate_decl): Use full template arguments. + (set_mangled_name_for_template_decl): New function. + * semantics.c (begin_class_definition): Use + maybe_process_partial_specialization. + (finish_member_class_template): New function. + (finish_template_decl): Likewise. + (finish_template_type): Likewise. + (typeck.c): Don't crash after issuing a compiler_error. + * Makefile.in (CONFLICTS): Adjust; we removed a s/r conflict. + +1998-07-27 Jason Merrill + + * typeck2.c (build_functional_cast): Handle default-initialization. + + * call.c (build_over_call): Pass 1 to popclass. + + * parse.y (direct_notype_declarator): Add precedence declaration + to notype_unqualified_id case. + * Makefile.in (EXPECT): Adjust. + + * tree.c (ovl_member): Fix for single function in OVL. + +1998-07-27 Dave Brolley + + * c-lex.c (yylex): Fix boundary conditions in character literal and + string literal loops. + +1998-07-24 Jason Merrill + + * decl.c (lookup_name_real): OK, do return the from_obj value + unless got_object depends on template parms. + + * parse.y (nested_name_specifier_1): Pull out the TYPE_MAIN_VARIANT. + + * pt.c (coerce_template_parms): Also complain about local enums. + + * cp-tree.h: Add prototype for set_identifier_local_value. + * decl.c (set_identifier_local_value_with_scope): Make static, + prototype. + * search.c (covariant_return_p): Likewise. + * except.c (build_terminate_handler, alloc_eh_object): Likewise. + + * call.c (build_method_call): Only pull out the type of a destructor + if it's a template type parm. + * decl.c (lookup_name_real): Never return the from_obj value. + +1998-07-23 Jason Merrill + + * except.c (process_start_catch_block_old): Call start_decl_1 for + catch parm. + * decl.c (start_decl_1): Avoid duplicate error. + + * init.c (expand_default_init): Only perform the initialization if + it will do something. + +1998-07-23 H.J. Lu (hjl@gnu.org) + + * parse.y (base_class): Check for invalid base class. + +1998-07-23 Jason Merrill + + * decl2.c (import_export_template): Fold in... + (import_export_class): ...to here. Handle dllimport/export. + + * class.c (build_vtable): Pass at_eof to import_export_vtable. + (prepare_fresh_vtable): Likewise. + * decl2.c (import_export_class): Split out... + (finish_prevtable_vardecl): From here. + * class.c (finish_struct_1): Call import_export_class if at_eof. + + * decl.c (start_function): #if 0 mysterious code I wrote and have + forgotten why. + * rtti.c (get_tinfo_fn): If this is for a class type, set + DECL_CONTEXT. + +1998-07-22 Jason Merrill + + * inc/exception: Change terminate and unexpected to (). + + * parse.y (named_class_head_sans_basetype_defn): A + named_class_head_sans_basetype followed by '{' or ':' is a defn. + +1998-07-21 Jason Merrill + + * tree.c (canonical_type_variant): New fn to handle arrays. + * cp-tree.h (CANONICAL_TYPE_VARIANT): Remove. + * pt.c (unify, default case): Also fold arg. Fix array bounds case. + * method.c (process_overload_item): Use build_overload_value for + arrays. + +1998-07-20 Dave Brolley + + * lex.c (mbchar.h): #include it. + (GET_ENVIRONMENT): New macro. + (init_parse): Set character set based on LANG environment variable. + (real_yylex): Handle multibyte characters in character literals. + (real_yylex): Handle multibyte characters in string literals. + +1998-07-19 Jason Merrill + + * lex.c (do_identifier): Look for class value even if we don't + have a global value. Do implicit declaration if parsing is 2. + * semantics.c (finish_call_expr): Pass 2 if we're doing Koenig + lookup. + +1998-07-19 Mark Mitchell + + * decl.c (pushtag): Revert previous change. + * pt.c (lookup_template_class): Don't put out debugging + information for types that use template parameters. + + * decl.c (pushtag): Don't put out debugging information for + compiler-generated typedefs. + + * error.c (dump_type_real): Don't crash when presented with + intQI_type_node or the like. + + * semantics.c (finish_translation_unit): Fix spelling error in + comment. + +1998-07-17 Jason Merrill + + * decl.c (lookup_name_real): Pull out single function here. + (select_decl): Not here. + (unqualified_namespace_lookup): Use CP_DECL_CONTEXT. + + * decl.c (qualify_lookup): Tweak again. + + * pt.c (lookup_template_class): Don't mess with the context of the + instantiation. + * decl2.c (current_decl_namespace): Remove special handling for + templates. + + * pt.c (tsubst, case FUNCTION_DECL): Fix getting complete args for + a member template specialization. + + * tree.c (ovl_member): Use decls_match to compare functions. + * decl.c (decls_match): Check the context of a function. + + * parse.y (primary): Use notype_unqualified_id instead of IDENTIFIER + in Koenig lookup support rules. + * semantics.c (finish_call_expr): Handle the new cases. + + * typeck.c (build_x_function_call): Handle overloaded methods. + + * decl.c (grokvardecl): Don't call build_static_name for extern "C". + +1998-07-16 Mark Mitchell + + * semantics.c (finish_object_call_expr): Revert previous change. + * call.c (build_new_method_call): Likewise. Instead, convert + TYPE_DECLs to IDENTIFIERs here, in the presence of templates. + +1998-07-16 Jason Merrill + + * decl.c (qualify_lookup): Handle templates. + + * decl2.c (do_using_directive): Don't pass ancestor. + * decl.c (push_using_directive): Calculate ancestor. + + * decl2.c (do_nonmember_using_decl): Allow for type shadowing. + * decl.c (pushdecl): Move type shadowing handling from here... + (duplicate_decls): ...to here. + * decl.c (set_identifier_local_value_with_scope): New fn. + (pushdecl): Use it. + (set_identifier_local_value, lookup_type_current_level): New fns. + * decl2.c (do_local_using_decl): Handle types and binding level + stuff properly. + + * init.c (build_offset_ref): Don't call mark_used on an OVERLOAD. + * decl.c (select_decl): Extract a lone function from an OVERLOAD. + (lookup_namespace_name): Likewise. + * typeck.c (build_unary_op): Not here anymore. + + * decl2.c (do_class_using_decl): Make sure we get an identifier. + * class.c (handle_using_decl): Ignore TYPE_DECLs. + + * decl.c (qualify_lookup): New fn. + (lookup_name_real): Use it. + +1998-07-16 Martin v. Loewis + + * decl2.c (add_using_namespace): When directly using a namespace + that was indirect before, promote it. + + * cp-tree.h (LOOKUP_PREFER_TYPES, LOOKUP_PREFER_NAMESPACES, + LOOKUP_PREFER_BOTH, LOOKUP_NAMESPACES_ONLY, LOOKUP_TYPES_ONLY, + LOOKUP_QUALIFIERS_ONLY, LOOKUP_TEMPLATES_EXPECTED): New macros. + * decl.c (select_decl): Replace two flag parameters by one. + (unqualified_namespace_lookup): Likewise, pass flag. + (lookup_flags): New function. + (lookup_name_real): Compute flags, pass them. + (lookup_namespace_name): Call with zero-flag. + * decl2.c (ambiguous_decl): Add flag parameter, complain only + according to flags. + (lookup_using_namespace, qualified_lookup_using_namespace): + Add flag parameter, pass them through. + * lex.c (do_scoped_id): Call with zero-flag. + +1998-07-16 Jason Merrill + + * typeck.c (convert_for_assignment): Use comptypes. + +1998-07-16 Mark Mitchell + + * semantics.c (finish_object_call_expr): Move test for the + function called being a TYPE_DECL to ... + * call.c (build_new_method_call): Here. + +1998-07-15 Jason Merrill + + * decl2.c (arg_assoc_class): Also look at template arguments, if any. + (arg_assoc): Handle error_mark_node and multiple levels of TREE_LIST. + + * lex.c (looking_for_typename): Don't initialize. + + * decl2.c (ambiguous_decl): Clarify error message. + + * decl.c (push_using_directive): Iterate over namespaces used + indirectly. + +1998-07-15 Martin v. Löwis + + * decl2.c (add_using_namespace): Iterate over namespaces used + indirectly. + + * decl.c (lookup_name_real): Accept namespace aliases as locals. + (cat_namespace_levels): Ignore aliases. + (duplicate_decls): Ignore duplicate aliases. + * decl2.c (do_namespace_alias): Process block level namespace + aliases. Store alias with pushdecl. Remove odr errors. + * parse.y (namespace_alias): New non-terminal. + (extdef): Use it. + +1998-07-15 Jason Merrill + + * decl2.c (arg_assoc_type): Handle METHOD_TYPE like FUNCTION_TYPE. + Handle TEMPLATE_TYPE_PARM. + (arg_assoc): Rewrite. + + * pt.c (complete_template_args): Don't look at the context unless + we have to. + + * method.c (build_decl_overload_real): Fix namespace handling. + + * typeck.c (build_unary_op): Extract a lone function from an + OVERLOAD. + + * call.c (build_scoped_method_call): Handle getting a namespace + for basetype in a destructor call. + (check_dtor_name): Handle enums. + + * parse.y (using_directive): New nonterminal. + (extdef, simple_stmt): Use it. + +1998-07-14 Martin von Löwis + + * decl2.c (add_function): Move error message ... + (arg_assoc_namespace): ... from here. + +1998-07-14 Jason Merrill + + * parse.y (namespace_qualifier): Fix multiple level handling. + * decl2.c (namespace_ancestor): Use CP_DECL_CONTEXT. + (arg_assoc): Don't skip the first argument of a function. + +Tue Jul 14 20:09:22 1998 Jeffrey A Law (law@cygnus.com) + + * search.c (my_tree_cons): Clean up. + +1998-07-14 Jason Merrill + + * call.c (joust): Don't warn about "confusing" conversions to the + same type. + +1998-07-14 Martin von Löwis + + * class.c (push_nested_class): Complain about namespaces. + * decl.c (start_decl): Enter the object's namespace. + (cp_finish_decl): Leave it. + (grokdeclarator): Likewise. + * decl2.c (check_decl_namespace): New function. + (finish_file): Call it. + * parse.y (complex_direct_notype_declarator): Set complexity + of namespace-qualified ids to -1, enter the namespace. + + * method.c (build_template_decl_overload): Expect _DECL as first + parameter. Put context temporarily into current_namespace. + * pt.c (check_explicit_specialization): Change caller. + (tsubst): Likewise. + + * init.c (build_offset_ref): Call mark_used and + convert_from_reference for namespace members. + +Mon Jul 13 23:25:28 1998 Martin von Löwis + + * search.c (my_tree_cons): The bitfield is at index 2. + +Mon Jul 13 17:21:01 1998 Nick Clifton + + * lang-options.h: Format changed to work with new --help support + in gcc/toplev.c + +1998-07-12 Martin von Löwis + + * decl2.c (build_expr_from_tree): Change calls of do_identifier. + Do Koenig lookup in CALL_EXPR. + (arg_assoc): Handle error_mark. + * lex.c (is_global): New function. + (do_identifier): Expect arguments for Koenig lookup. + * parse.y (primary): Add rules for calls of unqualified function calls. + (do_id): Change call of do_identifier. + * pt.c (finish_stmt_expr): Likewise. + * semantics.c (finish_id_expr): Likewise. + (finish_call_expr): Add integer parameter to indicate + argument-dependent lookup. + + * decl.c (struct binding_level): New field using_directives. + (push_using_decl): Not sorry anymore. + (push_using_directive): New function. + (lookup_tag): Use CP_DECL_CONTEXT to iterate. + (unqualified_namespace_lookup): New function, code from ... + (lookup_name_real): ... here. + * decl2.c (lookup_using_namespace): Pass using list instead of + initial scope. + (validate_nonmember_using_decl): New function. + (do_nonmember_using_decl): New function. + (do_toplevel_using_decl): Use them. + (do_local_using_decl): New function. + (do_using_directive): Support block-level directives. + * parse.y (simple_stmt): Support using declarations and + directives. + (namespace_qualifier, namespace_using_decl): New non-terminals. + + * xref.c (classname): New function. + (GNU_xref_hier): Change class and base parameters to tree. + * decl.c (xref_baseypes): Change caller. + * friend.c (make_friend_class): Likewise. + +1998-07-12 Kriang Lerdsuwanakij + + * typeck.c (comptypes, case TEMPLATE_TEMPLATE_PARM): Add parameter + comparison. + + * pt.c (for_each_template_parm, case TEMPLATE_DECL): If it is a + template template parameter, record its use. + (for_each_template_parm, case TEMPLATE_TEMPLATE_PARM): Traverse + its template arguments if exists. + + * pt.c (coerce_template_template_parms): New function equivalent + to coerce_template_parms when IS_TMPL_PARM is true. + (coerce_template_parms): Use it. Remove the IS_TMPL_PARM parameter, + all callers changed. + + (coerce_template_parms): Access ARGLIST properly when creating a + new vector. Only accept implicit TYPE_DECL as valid argument for + a template template parameter when it is a base class of + current_class_type. Don't display error message when COMPLAIN is + false. + +1998-07-12 Klaus Kaempf (kkaempf@progis.de) + + * repo.c (get_base_filename): Use file_name_nondirectory. + (open_repo_file): Likewise. + * cp-tree.h (file_name_nondirectory): Add prototype. + +1998-07-12 Jason Merrill + + * friend.c (do_friend): Pull the identifier out of declarator. + Use cp_error and friends. + * decl2.c (qualified_lookup_using_namespace): Fix call to + purpose_member. + * decl.c (lookup_name_real): Don't call complete_type on a namespace. + (grokvardecl): Use DECL_CLASS_SCOPE_P. + * cvt.c (convert_pointer_to_real): Check for error_mark_node sooner. + * class.c (warn_hidden): Fix for OVERLOAD. + From grahams@rcp.co.uk: + * cp-tree.h (DEFARG_NODE_CHECK): New macro. + (DEFARG_LENGTH, DEFARG_POINTER): Use it. + +Sun Jul 12 01:20:57 1998 Jeffrey A Law (law@cygnus.com) + + * g++.1 (-traditional): Remove duplicated documentation. + +1998-07-11 Mark Mitchell + + * method.c (flush_repeats): Add nrepeats parameter. + (issue_nrepeats): Likewise. + (is_back_referenceable_type): New function. Don't back-reference + TEMPLATE_TYPE_PARMs as well as simple types like integers. + (build_mangled_name_for_type): Likewise. + (build_mangled_name_for_type_with_Gcode): Likewise. + (lasttype): Remove. + (nrepeats): Likewise. + (Nrepeats): Likewise. + (start_squangling): Don't clear the variables removed above. + (end_squangling): Likewise. + (flush_repeats): Tidy. Use nrepeats parameter rather than + Nrepeats global. + (issue_nrepeats): Likewise, but with nrepeats global. Use + is_backreferenceable_type. + (build_overload_nested_name): Tidy. Add comment. Use + build_mangled_name_for_type. + (build_underscore_int): Comment. + (build_overload_scope_ref): Use build_mangled_name_for_type. + (build_overload_int): Likewise. + (build_template_template_parm_names): Tidy. + (build_template_parm_names): Use build_mangled_name_for_type. + (build_overload_identifier): Add comments. + (build_mangled_name_for_type_with_Gcode): Split out from + build_mangled_name. + (build_mangled_name_for_type): Use it. + (build_mangled_name): Rework to use build_mangled_name_for_type + and to not use global nrepeats/Nrepeats. Tidy. + (process_modifiers): Tidy. + (check_btype): Use is_backreferenceable_type. Add comment. + Rename `node' to `type'. + (process_overload_item): Set numeric_output_need_bar here. + Use build_mangled_name_for_type. Tidy. + (build_decl_overload_real): Tidy. Don't use Nrepeats. Use + build_mangled_name_for_type. + + * pt.c (push_template_decl_real): Don't look at DECL_TEMPLATE_INFO + for TYPE_DECLs. + +1998-07-08 Vladimir N. Makarov + + * cp-tree.h (warn_long_long): Define. + * decl.c (grokdeclarator): Add flag `warn_long_long' as guard for + warning "ANSI C++ does not support `long long'". + * decl2.c (warn_long_long): Define. + (lang_decode_option): Parse -Wlong-long, -Wno-long-long options. + +1998-07-07 Jason Merrill + + * decl.c (xref_tag): Handle attributes between 'class' and name. + * parse.y (aggr): Likewise. + * semantics.c (finish_class_definition): Likewise. + * Makefile.in (EXPECTED): Adjust. + + * cp-tree.h: Declare flag_optional_diags and warn_multichar. + * decl2.c: Define them. + (lang_decode_option): Handle them. + * lang-options.h: Add -foptional-diags. + * class.c (finish_struct): Don't complain about multiple meanings of + name if -fno-optional-diags. + * decl.c (pushdecl_class_level): Likewise. + * lex.c (real_yylex): Check warn_multichar. + +1998-07-06 Jason Merrill + + * decl.c (lookup_tag): Use CP_DECL_CONTEXT. + + * tree.c (make_binfo): Fix length. + +1998-06-30 Benjamin Kosnik + + * decl2.c (lang_decode_option): Remove warn_template_debugging. + * lang-options.h: Likewise. + +Mon Jun 29 20:17:40 1998 Kaveh R. Ghazi + + * except.c (build_eh_type_type_ref): Remove unused variable `susp'. + (process_start_catch_block): Likewise for variables + `false_label_rtx', `call_rtx' and `return_value_rtx'. + +1998-06-29 Brendan Kehoe + + * tree.c (build_srcloc): Make sure we allocate this node on the + permanent obstack. + +Sat Jun 27 23:34:18 1998 Fred Fish + + * g++spec.c (NEED_MATH_LIBRARY): Define to 1 if not already defined. + (lang_specific_driver): Initialize need_math with NEED_MATH_LIBRARY. + (lang_specific_driver): Only add -lm automatically if need_math is + nonzero. + +Sat Jun 27 12:22:56 1998 Jeffrey A Law (law@cygnus.com) + + * Make-lang.in (g++): Depend on mkstemp.o. Link in mkstemp.o + +Sat Jun 27 07:36:09 1998 Kaveh R. Ghazi + + * Makefile.in (EXPR_H): New dependency variable. + (decl2.o): Depend on $(EXPR_H). + (typeck.o): Likewise. + (init.o): Likewise. + (expr.o): Likewise. + +1998-06-25 Benjamin Kosnik + + * decl.c (start_enum): Put local enums on permanent_obstack. + +1998-06-25 Mark Mitchell + + * cp-tree.h (c_get_alias_set): Declare. + * decl.c (init_decl_processing): Set lang_get_alias_set. + +1998-06-25 Andrew MacLeod + + * cp-tree.h (mark_all_runtime_matches): Add function prototype. + * except.c (mark_all_runtime_matches): Set TREE_SYMBOL_REFERENCED + flag for all function decls which are in the exception table. + * exception.cc (__cplus_type_matcher): Check for CATCH_ALL_TYPE match. + * decl2.c (finish_file): Call mark_all_runtime_matches to make sure + code is emitted for any referenced rtti function. + +1998-06-25 Dave Brolley + + * lang-specs.h: Use new | syntax to eliminate + string concatenation. + +1998-06-25 Jason Merrill + + * cp-tree.h (CP_DECL_CONTEXT): New macro. + * decl2.c (is_namespace_ancestor, lookup_using_namespace): Use it. + * method.c (build_overload_nested_name): Likewise. + * sig.c (build_signature_pointer_or_reference_type): Don't set + DECL_CONTEXT. + +1998-06-24 Martin v. Löwis + + Set DECL_CONTEXT for globals to NULL_TREE instead of global_namespace. + * cp-tree.h (FROB_CONTEXT): New macro. + (DECL_MAIN_P): ::main should have a DECL_CONTEXT of NULL_TREE. + * decl.c (namespace_binding): Replace NULL_TREE with + global_namespace. + (set_namespace_binding, pop_namespace, lookup_name_real): Likewise. + * decl2.c (is_namespace_ancestor, lookup_using_namespace): + Likewise. + * decl.c (pushtag): Use FROB_CONTEXT. + (pushdecl, make_typename_type, define_function, grokdeclarator): + Likewise. + * decl2.c (set_decl_namespace, do_namespace_alias): Likewise. + * pt.c (push_template_decl_real, lookup_template_class, tsubst): + Likewise. + * decl2.c (decl_namespace): Return global_namespace if no context. + * method.c (build_overload_nested_name): Expect null as context. + * pt.c (mangle_class_name_for_template): Do nothing for null + contexts. + (lookup_template_class): Allow for null id_context. + +1998-06-25 Richard Henderson + + * method.c (emit_thunk): Set current_function_is_thunk for the + ASM_OUTPUT_MI_THUNK case as well. + +1998-06-23 Andrew MacLeod + + * exception.cc (__cplus_type_matcher): Get a match_info pointer + instead of an exception table entry as a parameter. + +1998-06-23 Andrew MacLeod + + * parse.y (function_try_block): Don't call start_catch_handler. + * except.c (call_eh_info): Remove coerced field from declaration. + (build_eh_type_type_ref): New function to create an address of a + rtti function for the new style exception tables. + (expand_start_catch_block): Split function, this contains the + common part. + (process_start_catch_block_old): New function to perform the rest + of expand_start_catch_block under old style exceptions. + (process_start_catch_block_old): New function to perform the rest + of expand_start_catch_block under new style exceptions. + (expand_end_catch_block): Only pop the false label off the stack under + the old style of exceptions. + * semantics.c (finish_try_block): Don't call start_catch_handler. + * exception.cc (struct cp_eh_info): Add original_value field. + (__cplus_type_matcher): Perform type matching on the original exception + value, and if we have a match, set the current value. + (__cp_push_exception): Set the original exception value. + +1998-06-23 Jason Merrill + + * call.c (joust): Fix confusing conversion warning. + + * call.c (build_op_delete_call): Add placement parm. Check + LOOKUP_SPECULATIVELY. + * cp-tree.h, decl2.c, init.c: Adjust. + * decl.c (finish_function): Use it. + + * pt.c (tsubst): Diagnose creating void fields or variables. + +Mon Jun 22 08:50:26 1998 Kaveh R. Ghazi + + * call.c (build_scoped_method_call): Remove unused variable `tmp'. + + * cp-tree.h (check_dtor_name): Add prototype. + + * init.c (expand_member_init): Remove unused variables + `ptr_type_node', `parm' and `rval'. + + * ptree.c (print_lang_type): Use HOST_WIDE_INT_PRINT_DEC specifier + in call to fprintf. + (lang_print_xnode): Likewise. + + * typeck2.c (enum_name_string): Cast argument to sprintf to long + and use %ld specifier. + + * xref.c (GNU_xref_end_scope): Use HOST_WIDE_INT_PRINT_DEC + specifier in call to fprintf. + (GNU_xref_member): Cast argument to sprintf to int. + +Fri Jun 19 23:22:42 1998 Bruno Haible + + * typeck2.c (pop_init_level): Warn about implicit zero initialization + of struct members. + +Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi + + * cp-tree.h: Prototype function `check_java_method'. + +1998-06-17 Jason Merrill + + * class.c (finish_struct): Make conflicting use of id a pedwarn. + * decl.c (pushdecl_class_level): Likewise. + +1998-06-17 Mark Mitchell + + * pt.c (convert_nontype_argument): Issue an error when presented + with an integer (real) constant that cannot be simplified to an + INT_CST (REAL_CST). + + * cp-tree.h (c_get_alias_set): Remove declaration added in + 1998-06-13 change that should never have been checked in. + +1998-06-17 Jason Merrill + + * typeck.c (build_binary_op_nodefault): Change % in format strings + to %%. + + * decl.c (grokvardecl): Don't build_static_name for decls that + aren't at namespace scope. + + * init.c (perform_member_init): Catch default-initialization of + references. + +1998-06-17 Mark Mitchell + + * errfn.c (cp_thing): Handle the `%%' formatting sequence. + +1998-06-17 Jason Merrill + + * method.c (hack_identifier): Complain about getting a namespace + or class template. + * typeck.c (decay_conversion): Remove check for namespaces. + * typeck2.c (incomplete_type_error): Likewise. + * parse.y (template_arg): Add PTYPENAME expansion. + +1998-06-16 Andrew MacLeod + + * decl.c (grokvardecl): Don't build external assembler names for + TYPENAMEs in other namespaces as there is no declarator. + * error.c (cp_file_of, cp_line_of): Don't extract file or line number + info from DECL_CONTEXT if it is NULL. + +1998-06-16 Jason Merrill + + * call.c (check_dtor_name): Split out. + (build_scoped_method_call): Use it. + (build_method_call): Use it. + * init.c (build_offset_ref): Use it. + + * typeck.c (build_static_cast): Fix handling of pointers to members. + + * decl.c (finish_function): Just return nothing from a constructor. + * typeck.c (c_expand_return): Complain about returning a void + expression from a destructor. + +1998-06-13 Mark Mitchell + + * class.c (alter_access): Accept a BINFO explaining how to get + from the entity whose accessed is being altered to the type doing + the altering. + (handle_using_decl): New function containing code split out from ... + (finish_struct_1): Here. + + * cp-tree.h (complete_type_or_else): Declare. + * init.c (build_new_1, build_delete): Use it. + * typeck.c (require_complete_type): Use complete_type, rather than + expanding it inline. + (complete_type_or_else): New function. + (build_component_ref): Use it. + (pointer_int_sum): Make sure the type pointed to is complete. + (pointer_diff): Likewise. + + * pt.c (for_each_template_parm): Traverse the TYPE_CONTEXT for + types. + + * search.c (get_matching_virtual): Note that member templates + cannot override virtual functions. + +1998-06-12 Brendan Kehoe + + * pt.c (check_explicit_specialization): If DECLARATOR turned into + an error_mark_node from lookup_template_function, return the same. + (determine_specialization): Also make sure TEMPLATE_ID isn't an + error_mark_node, before we try to read its operands. + * decl.c (grokdeclarator): If we got an error_mark_node from + check_explicit_specialization, just return it right back. + +1998-06-12 Mark Mitchell + + * class.c (instantiate_type): Don't treat template-ids that don't + specify any template arguments as equivalent to ordinary + identifiers. Use OFFSET_REF instead of SCOPE_REF to refer to + pointer-to-members for member templates. Tidy slightly. + * cp-tree.def (TEMPLATE_ID_EXPR): Revise documentation. + * init.c (build_offset_ref): Handle template-ids like ordinary + identifiers, for the most part, but store a TEMPLATE_ID_EXPR in the + offset part of the OFFSET_REF. + * typeck.c (build_unary_op): Change check for unknown types to + look for OFFSET_REFs, not SCOPE_REFs. + +1998-06-11 Mark Mitchell + + * pt.c (is_member_template_class): New function. + (push_template_decl_real): Use it. + +1998-06-11 Benjamin Kosnik + + * friend.c (do_friend): Add support for nested classes using + member functions of the enclosing class as friends. + +1998-06-10 Mark Mitchell + + * call.c (convert_default_arg): Make global, not static. + (convert_arg_for_ellipsis): Split out from ... + (build_over_call): Here. + * cp-tree.h (convert_default_arg); Declare. + (convert_arg_to_ellipsis): Likewise. + (do_member_init): Remove. + * init.c (do_member_init): Remove; this code is dead. + (expand_member_init): Remove much of this code; it is dead. + * typeck.c (convert_arguments): Use convert_default_arg and + convert_arg_for_ellipsis, rather than duplicating here. + + * call.c (convert_like): Don't fail silently if + build_user_type_conversion fails. Always return error_mark_node + for failure. + +1998-06-10 Jason Merrill + + * search.c (covariant_return_p): Complain about ambiguous base. + + * typeck.c (build_component_ref): Diagnose ref to nested type. + +1998-06-10 Brendan Kehoe + + * decl.c (grokparms): Check that INIT isn't an error_mark_node + before giving error about invalid type for default arg. + +1998-06-10 Jason Merrill + + * call.c (build_method_call): Fix thinko. + +1998-06-10 Dave Brolley + + * decl2.c (lang_decode_option): New argc/argv interface. + * cp-tree.h (lang_decode_option): New argc/argv interface. + * lang-specs.h (default_compilers): Only call cpp if -E, -M or -MM is + specified for cpplib-enabled compilers. + * lex.c (lang_init): Don't check_newline for cpplib. + (init_parse): Don't initialize cpplib here. + +1998-06-10 Brendan Kehoe + + * typeck.c (build_component_ref): Make sure FIELD has a lang_specific + piece before checking DECL_MUTABLE_P. + +1998-06-10 John Carr + + * tree.c (debug_binfo): Make printf format match arguments. + + * error.c (OB_PUTI): Make printf format match arguments. + +1998-06-10 Jason Merrill + + * init.c (perform_member_init): Handle default-initialization. + + * except.c (build_throw): Handle throwing NULL. + + * typeck.c (build_x_function_call): Use resolve_offset_ref. + + * search.c (compute_access): Only strip an anonymous union + for a FIELD_DECL. + + * call.c (add_builtin_candidates): Tweak. + + * cvt.c (build_expr_type_conversion): Restore code for conversion + from class types. + * decl2.c (delete_sanity): Use it. Clean up. + + * typeck.c (comp_ptr_ttypes_real): Fix cv-qual comparisons. + +1998-06-10 Branko Cibej + + * typeck.c (c_expand_return): Don't warn about void expressions on + return statements in functions returning void. + +1998-06-09 Mark Mitchell + + * pt.c (fn_type_unification): Revise documentation. Tidy. + (type_unification): Likewise. + +1998-06-09 Andrew MacLeod + + * semantics.c (finish_try_block): Rename expand_start_catch, and delete + expand_end_catch. + * parse.y (function_try_block): Rename expand_start_catch, and delete + expand_end_catch. + * except.c (expand_end_eh_spec): Rename expand_start_catch, and delete + expand_end_catch. + +1998-06-09 Jason Merrill + + * search.c (lookup_member): New fn. + * class.c (finish_struct_1): Use it. + * decl.c (lookup_name_real): Use it. + +Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi + + * Makefile.in (decl2.o): Depend on dwarf2out.h and dwarfout.h. + + * cp-tree.h: Add prototype for `maybe_print_template_context' and + `maybe_make_one_only'. + + * decl.c (auto_function): Remove unused variable `decl'. + + * decl2.c: Include dwarf2out.h and dwarfout.h. + + * lex.c: Remove redundant declarations of `set_float_handler' and + `asm_out_file'. + +1998-06-08 Andrew MacLeod + + * except.c (init_exception_processing): Remove NEW_EH_MODEL compile + time flag. Call __cp_eh_info instead of __cp_exception_info. + * exception.cc (struct cp_eh_info): Remove NEW_EH_MODEL flag. + (__cp_exception_info): Return offset into cp_eh_info structure to + match what use to be the start of this structure. + (__cp_eh_info): New function to return a pointer to cp_eh_info struct. + (__cplus_type_matcher, __cp_push_exception): Remove NEW_EH_MODEL + compile time flag. + (__uncatch_exception, __check_eh_spec, std::uncaught_exception): Call + __cp_eh_info instead of __cp_exception_info. + +1998-06-08 Jason Merrill + + * decl.c (cp_finish_decl): Disable inlining of extern inlines + with static variables. + +1998-06-08 Mark Mitchell + + * init.c (build_offset_ref): Correct previous change to use build, + not build_min. + +1998-06-07 Mark Mitchell + + * class.c (instantiate_type): Handle pointer-to-members where the + member is a template. + * init.c (build_offset_ref): Likewise. + * typeck.c (build_unary_op): Likewise. + +1998-06-07 Richard Henderson + + * lex.c (lang_init_options): New function. + (lang_init): Remove flag_exceptions == 2 hack. + +1998-06-05 Jason Merrill + + * search.c (envelope_add_decl): Tweak for implicit typename. + + * call.c (joust): Also warn about confusing conversion op/constructor + overload resolution. + + * spew.c (yylex): Also return the TYPE_DECL if got_object. + Don't clear got_object after '~'. + * call.c (build_scoped_method_call): Tweak destructor handling. + (build_method_call): Likewise. + * pt.c (tsubst_copy, case METHOD_CALL_EXPR): Don't mess with + TYPE_MAIN_VARIANT for destructors. + * semantics.c (finish_object_call_expr): Complain about calling a + TYPE_DECL. + +1998-06-05 Per Bothner + + * g++spec.c (lang_specific_pre_link, lang_specific_extra_ofiles): + Define - update needed by gcc.c change. + +1998-06-05 Jason Merrill + + * error.c (cp_printers): Use 'o' instead of '_' for the null entry. + +1998-06-05 Martin v. Loewis + + * cp-tree.h (DECL_NAMESPACE_ALIAS, ORIGINAL_NAMESPACE): Declare. + * decl.c (lookup_name_real): Add namespaces_only parameter. + If set, return only NAMESPACE_DECLs. + (select_decl): Likewise. + (identifier_type_value): Give additional parameter. + (lookup_name_nonclass): Likewise. + (lookup_name): Likewise. + (find_binding): Skip namespace aliases. + (binding_for_name): Likewise. + (push_namespace): Check for namespace aliases. + (lookup_name_namespace_only): New function. + (begin_only_namespace_names, end_only_namespace_names): New functions. + * decl2.c (set_decl_namespace): Skip namespace aliases. + (do_using_directive): Likewise. + (do_namespace_alias): Produce namespace aliases, fix alias + redeclaration. + * error.c (dump_decl): Support SCOPE_REF. + * parse.y (extdef): Wrap lookup with namespace_only for namespace + aliases and using declarations. + +1998-06-04 Jason Merrill + + * tree.c (really_overloaded_fn): Only see through one TREE_LIST. + + * error.c (dump_expr): Clean up NEW_EXPR case. + +1998-06-04 Martin von Löwis + + Suggested by Brendan Kehoe + * decl2.c (do_toplevel_using_decl): When decl is a TYPE_DECL, + treat it as using ::decl. + + * decl2.c (arg_assoc_type): Process unknown_type_node and OFFSET_TYPE. + + * tree.c (mapcar): Support NEW_EXPR. + + * error.c (dump_expr): Support NEW_EXPR. + +1998-06-03 Jason Merrill + + * method.c (make_thunk): Use overload machinery to make name. + * search.c (covariant_return_p): New fn. + (get_matching_virtual): Use it. + + * init.c (build_new_1): Fix check for void. + +1998-06-01 Per Bothner + + * cp-tree.h (TYPE_FOR_JAVA): New macro. + * decl.c, cp-tree.h (java_byte_type_node, java_short_type_node, + java_int_type_node, java_long_type_node, java_float_type_node, + java_double_type_node, java_char_type_node, java_boolean_type_node): + New "primitive" types, with predefined names __java_byte etc. + (record_builtin_java_type): New function. + (init_decl_processing): Make Java types with record_builtin_java_type. + (pushtag, grokdeclarator): Set TYPE_FOR_JAVA if in extern "JAVA". + (xref_baseypes): If base class was TYPE_FOR_JAVA, so is this class. + (grokfndecl): Call check_java_method for Java classes. + * method.c (is_java_type): Removed. Replaced with TYPE_FOR_JAVA. + (process_overload_item): Match types against specific + java_XX_type_node types, rather than using is_java_type. + * class.c (finish_struct_1): Don't add default copy constructor + or operator= if TYPE_FOR_JAVA. + (pop_lang_conext): Restore strict_prototyp proper if Java. + * decl2.c (acceptable_java_type, check_java_method): New functions. + * pt.c (instantiate_class_template): Copy TYPE_FOR_JAVA from pattern. + (tsubst): Move common statement after if statement. + * typeck.c (comptypes): If strict, TYPE_FOR_JAVA must match. + +1998-06-01 Jason Merrill + + * pt.c (for_each_template_parm): Use first_rtl_op. + + * tree.c (build_cplus_array_type_1): Also check index_type for + template parms. + +1998-05-31 Jason Merrill + + * pt.c (tsubst): Always copy BINFO_BASETYPES. + +1998-05-29 scott snyder + + * tree.c (layout_basetypes): If we change TYPE_SIZE, change + TYPE_SIZE_UNIT too. + +1998-05-29 Mark Mitchell + + * decl.c (grokdeclarator): Don't complain about in-class + initialization of static consts if we don't really know the type + of the variable. + +1998-05-29 Jason Merrill + + * cp-tree.h (DECL_DESTRUCTOR_P): New macro. + * method.c (build_destructor_name): New fn. + * decl2.c (maybe_retrofit_in_chrg): Split out... + (grokclassfn): From here. Reorganize. + * decl.c (grok_ctor_properties): Make sure ctors for types with + vbases have the in_chrg parm. + * pt.c (instantiate_class_template): Update + TYPE_USES_VIRTUAL_BASECLASSES from tsubsted bases. Don't call + grok_*_properties. + (tsubst): Call grok_ctor_properties and maybe_retrofit_in_chrg. + +1998-05-28 Mark Mitchell + + * pt.c (instantiate_decl): Make test for whether or not static + variables should be instantiated early match its comment. + +1998-05-28 Jason Merrill + + * decl.c (start_decl): Always pedwarn about vacuously redeclaring + a member. + (start_function): Call check_default_args. + * decl2.c (grokfield): Don't call check_default_args. + (check_default_args): Use cp_error_at. + * lex.c (do_pending_defargs): Call check_default_args. + +1998-05-27 Brendan Kehoe + + * call.c (build_method_call): Make sure get_type_value returns + something before we try to use its TYPE_MAIN_VARIANT. + (build_scoped_method_call): Likewise. + +1998-05-27 Jason Merrill + + * typeck2.c (digest_init): Complain about getting a TREE_LIST to + initialize an array. + + * search.c (expand_upcast_fixups): Don't set DECL_CONTEXT and + DECL_VIRTUAL_P. + + * friend.c (do_friend): Clarify template warning. + +1998-05-27 Mark Mitchell + + * decl.c (shadow_label): Don't treat decls as identifiers. + (maybe_push_to_top_level): Clear shadowed_labels. + + * pt.c (instantiate_decl): Reset lineno and filename after calling + regenerate_decl_from_template. + + * decl.c (grokdeclarator): Don't try to use TYPE_OBSTACK on an + error_mark_node. + +1998-05-27 Kevin Buhr + + * parse.y (base_class): Use is_aggr_type, not IS_AGGR_TYPE. + +1998-05-26 Kriang Lerdsuwanakij + + * pt.c (process_template_parm): Accept TYPENAME_TYPE nodes. + (convert_nontype_argument): Handle cases when nontype template + parameters become classes after substitution. + +1998-05-26 Mark Mitchell + + * friend.c (is_friend): Use comptypes, rather than == to compare + types. Modify for new representation of template friends. + (make_friend_class): Likewise. + * pt.c (tsubst_friend_class): Undo 1998-05-21 change. Tweak. + (instantiate_class_template): Deal with template friends. + + * decl.c (store_parm_decls): Remove redundant call to + expand_main_function. + +1998-05-26 Benjamin Kosnik + + * decl.c (start_decl): Check for DECL_LANG_SPECIFIC before + DECL_USE_TEMPLATE. + +1998-05-26 Per Bothner + + * language_as_string: Handle lang_java. + +1998-05-26 Jason Merrill + + * decl.c (pushdecl): Don't copy the type_decl. + +1998-05-26 Martin v. Löwis + + * class.c (pushclass): Always store TYPE_MAIN_VARIANT in + current_class_type. + * decl.c (grokdeclarator): Put typedefs on the type's obstack. + + * parse.y (complex_direct_notype_declarator): Use $1 to access + scope of notype_qualified_id. + +1998-05-26 Dave Brolley + + * lex.c (parse_options,yy_cur,yy_lim): Add for cpplib. + (init_parse): Initialize cpplib interface. + + * Makefile.in (CXX_OBJS): Make sure dependencies never end with an + empty continuation. + +1998-05-26 Mark Mitchell + + * decl.c (pushtag): Avoid crashing on erroneous input. + +1998-05-25 Martin v. Löwis + + * decl.c (push_namespace): Only produce one unique name for + anonymous namespaces. + (get_unique_name): Remove. + +1998-05-25 Mark Mitchell + + * call.c (tourney): Don't do any extra comparisons. + + * decl2.c (build_anon_union_vars): Don't crash on empty sub-unions. + + * cp-tree.h (processing_template_parmlist): Declare. + * decl.c (pushtag): Don't call push_template_decl when we + shouldn't. + * pt.c (processing_template_parmlist): New variable. + (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro. + (complete_template_args): Use it. + (add_to_template_args): Likewise. + (innermost_args): Likewise. + (tsubst): Likewise. + (begin_template_parm_list): Use processing_template_parmlist. + (end_template_parm_list): Likewise. + + * cp-tree.h (ANON_UNION_TYPE_P): New macro. + * decl.c (grokdeclarator): Use it. + * decl2.c (grok_x_components): Likewise. + * init.c (initializing_context): Likewise. + * method.c (do_build_copy_constructor): Likewise. + (do_build_assign_ref): Likewise. + * search.c (compute_access): Likewise. + * typeck.c (build_component_ref): Likewise. + + * decl.c (grokdeclarator): Don't give a cv-qualified version of an + unnamed type a typedef name "for linkage purposes". + + * pt.c (lookup_template_class): Don't look at + IDENTIFIER_CLASS_VALUE when there's no current_class_type. + + * method.c (build_overload_int): Handle error cases gracefully. + + * pt.c (instantiate_decl): Handle static member variables + correctly. + + * pt.c (tsubst): Use the tsubst'd type when producing new + TEMPLATE_PARM_INDEX nodes. + +1998-05-24 Mark Mitchell + + * tree.c (cp_tree_equal): Handle pointers to member functions. + + * call.c (maybe_handle_implicit_object): Handle QUAL_CONVs. Make + sure the type of the REF_BIND is a reference type. + (maybe_handle_ref_bind, compare_ics): Rename reference_type to + target_type for clarity. + + * parse.y (xcond): Move call to condition_conversion ... + * semantics.c (finish_for_cond): Here. + * parse.c: Regenerated. + +1998-05-24 Jason Merrill + + * decl.c (push_namespace): Namespaces have type void. + * typeck2.c (incomplete_type_error): Complain about namespace + used as expression. + * typeck.c (decay_conversion): Likewise. + +1998-05-24 Martin von Löwis + + * error.c (dump_expr): Support namespaces. + +1998-05-23 Jason Merrill + + * cp-tree.def: Add SRCLOC. + * cp-tree.h: Add struct tree_srcloc and accessor macros. + * tree.c (build_srcloc, build_srcloc_here): New fns. + * pt.c (add_pending_template): Use build_srcloc_here. + (push_tinst_level): Update last_template_error_tick before erroring. + (instantiate_decl): Restore lineno and input_filename before + calling add_pending_template. + * decl2.c (finish_file): Set up lineno and input_filename for + pending templates. + +1998-05-22 Jason Merrill + + * decl.c (lang_print_error_function): New fn. + (init_decl_processing): Set print_error_function to use it. + * errfn.c (cp_thing): Don't call maybe_print_template_context here. + + * call.c (maybe_handle_ref_bind): Propagate ICS_USER_FLAG and + ICS_BAD_FLAG. + + * cvt.c (ocp_convert): Don't set LOOKUP_NO_CONVERSION for + copy-initialization. + + * class.c (build_vtable_entry): Use int_fits_type_p. + (build_vtable): Pass a signed offset to build_vtable_entry. + (prepare_fresh_vtable, modify_one_vtable, fixup_vtable_deltas1, + set_rtti_entry): Likewise. + +1998-05-22 Per Bothner + + * cp-tree.h: Add comments documenting which LANG_FLAGS are used. + (C_TYPE_VARIABLE_SIZE, C_DECL_VARIABLE_SIZE): Removed, not used. + +1998-05-22 Jason Merrill + + * pt.c (print_template_context): Use fprintf instead of cp_error. + + * pt.c (determine_specialization): Just return an error_mark_node. + Also print the decl we want in error messages. If we complain, + return error_mark_node. + (tsubst_friend_function): Set lineno and input_filename so + error messages will be useful. + (instantiate_template): Just return an error_mark_node. + (check_explicit_specialization): Don't mess with a returned + error_mark_node. + + * pt.c (print_template_context): Add new argument. + (maybe_print_template_context): New fn. + (push_tinst_level): Increment tinst_level_tick. + (pop_tinst_level): Likewise. + * errfn.c (cp_thing): Call maybe_print_template_context. Use + xrealloc instead of xmalloc. + + * typeck.c (build_unary_op, CONVERT_EXPR): Propagate TREE_CONSTANT. + +1998-05-21 Jason Merrill + + * pt.c (tsubst_friend_class): Don't call redeclare_class_template + if the template we looked up is the same as the one we already + have. + +Thu May 21 11:54:44 1998 Dave Brolley + + * lex.c: (handle_sysv_pragma): FILE* parameter not used. + (cpp_reader,parse_in): Add for cpplib. + (check_newline): Call handle_sysv_pragma with new interface. + (check_newline): Call GET_DIRECTIVE_LINE, not get_directive_line. + + * input.c: (yy_cur,yy_lim,yy_get_token,GETC): Add for cpplib. + (sub_getch): Call GETC for cpplib. + + * cp-tree.h: (get_directive_line): Different prototype for cpplib. + (GET_DIRECTIVE_LINE): Macro wrapper for get_directive_line. + + * Makefile.in (CXX_OBJS): Add @extra_cxx_objs@ for cpplib. + +1998-05-21 Jason Merrill + + * decl2.c (maybe_make_one_only): New fn. + (import_export_vtable): Use it. + (import_export_decl): Likewise. + * pt.c (mark_decl_instantiated): Likewise. + +1998-05-21 Mark Mitchell + + * decl2.c (find_representative_member): Rename to ... + (build_anon_union_vars): New function. + (finish_anon_union): Fix stupidity of previous change. + +1998-05-20 Jason Merrill + + * decl.c (grokfndecl): Handle definition of specialization in + friend declaration. + + * error.c (dump_decl): Fix LOOKUP_EXPR handling. + +1998-05-20 Mark Mitchell + + * class.c (delete_duplicate_fields_1): Use DECL_DECLARES_TYPE_P + to look for type declarations. + (finish_struct): Deal with templates on the CLASSTYPE_TAGS list. + * cp-tree.h (DECL_DECLARES_TYPE_P): New macro. + (finish_member_class_template): Declare. + * decl.c (pushtag): Put member class templates on the + CLASSTYPE_TAGS list, just as for ordinary member classes. + (pushdecl_class_level): Use DECL_DECLARES_TYPE_P. + (lookup_tag): Look for IDENTIFIER_CLASS_VALUEs, just as with + IDENTIFIER_NAMESPACE_VALUEs. + * parse.y (component_decl): Move code to ... + * semantics.c (finish_member_class_template): New function. + Don't put member class templates on the list of components for a + class. + * parse.c: Regenerated. + * pt.c (classtype_mangled_name): Don't try DECL_CONTEXT on types. + In fact, don't use DECL_CONTEXT at all here. + +1998-05-20 Martin von Loewis + + * decl.c (record_unknown_type): New function. + (init_decl_processing): Call it for the unknown and global type + nodes. + +1998-05-20 Mark Mitchell + + * decl2.c (find_representative_member): New function. + (finish_anon_union): Use it. + + * cp-tree.h (MAIN_NAME_P): New macro. + (DECL_MAIN_P): Likwise. + * decl.c (pushdecl): Avoid crashing on redefinitions of `main'. + (grokfndecl): Use the new macros. + (grokdeclarator): Likewise. + (start_function): Likewise. + (store_parm_decls): Likewise. + (finsh_function): Likewise. + * friend.c (do_friend): Likewise. + * typeck.c (build_function_call_real): Likewise. + (build_unary_op): Likewise. + +Wed May 20 02:16:01 1998 Jason Merrill + + * decl2.c (start_objects, finish_objects, do_dtors, + do_ctors): Split out from... + (finish_file): ...here. + +Tue May 19 20:36:23 1998 Jason Merrill + + * tree.c (is_overloaded_fn): Don't abort on placeholders from + push_class_decls. + +Tue May 19 15:16:22 1998 Brendan Kehoe + + * class.c (is_empty_class): Return 0 if TYPE is an error_mark_node. + + * error.c (dump_expr): Handle an ARROW_EXPR. + +Tue May 19 15:13:39 1998 Mark Mitchell + + * decl.c (saveable_obstack): Declare. + (pushdecl): Copy TYPE_DECLs to the same obstack as the type they + declare, if necessary. + +Tue May 19 14:50:27 1998 Mark Mitchell + + * call.c (compare_qual): Remove. + (is_subseq): Tweak. + (is_properly_derived_from): New function. + (maybe_handle_ref_bind): Likewise. + (maybe_handle_implicit_object): Likewise. + (compare_ics): Modify substantially to bring into conformance with + the standard. + * cp-tree.h (TYPE_PTRMEMFUNC_OBJECT_TYPE): New macro. + (comp_cv_qualification): Declare. + (comp_cv_qual_signature): Likewise. + * typeck.c (comp_cv_qualification): Likewise. + (comp_cv_qual_signature): Likewise. + +Tue May 19 10:05:02 1998 Kaveh R. Ghazi + + * Makefile.in (parse.o): Depend on toplev.h. + + * class.c (typecode_p): Remove prototype and definition. + + * cp-tree.h (currently_open_class, is_empty_class, member_p): + Add prototype. + + * decl.c (push_overloaded_decl_top_level): Remove prototype and + definition. + + * errfn.c (cp_error): Cast function pointer `error' to (errorfn *) + in call to `cp_thing'. + (cp_warning): Likewise for function pointer `warning'. + + * except.c (do_function_call): Remove prototype and definition. + (call_eh_info): Wrap variable `t1' in macro NEW_EH_MODEL. + + * method.c (is_java_type): Add prototype and make it static. + + * parse.y: Include toplev.h. + + * pt.c (type_unification): Remove unused variable `arg'. + (instantiate_decl): Likewise for `save_ti'. + + * tree.c (propagate_binfo_offsets): Likewise for `base_binfos'. + +Tue May 19 02:43:25 1998 Jason Merrill + + * init.c (build_member_call): Handle template_ids. + * parse.y (primary): Add global_scope template_id. + +Mon May 18 23:22:52 1998 Jason Merrill + + * decl2.c (get_sentry): Use end_temporary_allocation. + Don't declare permanent_obstack. + +Mon May 18 12:28:44 1998 Mark Mitchell + + * parse.y (.finish_new_placement): New non-terminal. + (unary_expr, new_type_id): Use it. + * parse.c: Regenerated. + +Mon May 18 12:20:27 1998 Brendan Kehoe + + * pt.c (redeclare_class_template): Say where the original definition + of the template-parameter's default argument appeared. + +Mon May 18 03:00:57 1998 Jason Merrill + + * call.c (build_over_call): Tweak empty class handling. + + * decl.c (make_typename_type): Use currently_open_class. + + * class.c (instantiate_type): Don't abort on TREE_NONLOCAL_FLAG. + +Mon May 18 01:43:01 1998 Martin v. Loewis + + * decl.c (lookup_name_real): Don't look at IDENTIFIER_LOCAL_VALUE + for a type unless it is one. + + * class.c (finish_struct_1): Use OVL_CURRENT in error message. + +Mon May 18 01:24:08 1998 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (program_transform_name, objdir): Define. + + * Makefile.in (BISON): Use bison from the build tree if it exists. + (FLEX): Likewise. + +Sun May 17 14:52:08 1998 Martin v. Loewis + + * typeck.c (type_unknown_p): Return true for TREE_LIST also. + + * call.c (build_method_call): Use TYPE_MAIN_VARIANT on typedefs. + +Sun May 17 14:51:41 1998 Jason Merrill + + * call.c (build_scoped_method_call): Likewise. + +Sun May 17 13:53:48 1998 Mark Mitchell + + * init.c (build_new_1): Call suspend_momentary around the creation + of values that must be saved for exception handling. + * parse.y (.build_new_placement): New non-terminal. + (unary_expr, new_placement): Use it. + * parse.c: Regenerated. + +Sun May 17 12:32:08 1998 Jason Merrill + + * decl.c (duplicate_decls): Use CANONICAL_TYPE_VARIANT to compare + old and new types. + + * pt.c (tsubst): Make sure that BINFO_TYPE of new binfos is the + canonical type. + + * call.c (build_over_call): Don't use IS_SIGNATURE on a namespace. + +Fri May 15 20:28:00 1998 Jason Merrill + + * decl.c (start_decl): Revert problem change. + + * Makefile.in (CONFLICTS): Fix. + +Fri May 15 15:34:02 1998 Benjamin Kosnik + + * decl.c (duplicate_decls): Clean up, add DECL_DATA_AREA bits. + +Fri May 15 00:46:05 1998 Jason Merrill + + * class.c (finish_struct_1): Use BINFO_SIZE. + + * decl.c (start_decl): Use 'tem'. + +Thu May 14 16:30:47 1998 Andrew MacLeod + + * exception.cc: Include eh-common.h. + (struct cp_eh_info): Add eh_info struct with NEW_EH_MODEL. + (__cplus_type_matcher): First stab at new C++ runtime type matcher. + (__cp_push_exception): Initialize eh_info struct as well. + * except.c: Remove local structs and include eh-common.h. + (init_exception_processing): Set language and version codes. + (call_eh_info): Add presence of eh_info to runtime description of + struct cp_eh_info. + (expand_end_eh_spec): Call start_catch_block() and end_catch_block(). + * semantics.c (finish_try_block): Call start_catch_block() and + end_catch_block(). + * parse.y (function_try_block): Call start_catch_block() and + end_catch_block(). + +Thu May 14 12:27:34 1998 Brendan Kehoe + + * typeck.c (original_type): New function. + (common_type): Use it to get the DECL_ORIGINAL_TYPE for T1 and T2, + to see if they're actually the same. + * cp-tree.h (original_type): Declare. + +Wed May 13 12:54:30 1998 Kaveh R. Ghazi + + * Makefile.in (lex.o): Depend on output.h. + + * call.c (add_function_candidate): Remove unused variable `cand'. + (add_conv_candidate): Likewise. + (build_builtin_candidate): Likewise. + + * cp-tree.h: Add prototype for `types_overlap_p'. + + * decl.c (signal_catch): Mark parameter `sig' with ATTRIBUTE_UNUSED. + + * decl2.c (merge_functions): Remove unused variables `tmp' and + `tempn'. + + * error.c (expr_as_string): Mark parameter `v' with ATTRIBUTE_UNUSED. + (code_as_string): Likewise. + (language_as_string): Likewise. + (parm_as_string): Likewise. + (op_as_string): Likewise. + (assop_as_string): Likewise. + (cv_as_string): Likewise. + + * lex.c: Include output.h. + + * pt.c (type_unification): Cast first argument of `bzero' to a char*. + + * search.c (dfs_no_overlap_yet): Mark parameter `t' with + ATTRIBUTE_UNUSED. + + * tinfo.cc (__class_type_info::dcast): Change the type of variable + `i' from int to size_t. + + * typeck.c (language_lvalue_valid): Mark parameter `exp' with + ATTRIBUTE_UNUSED. + +Tue May 12 21:37:49 1998 Jason Merrill + + * error.c (dump_simple_decl): Use DECL_CLASS_SCOPE_P and/or + DECL_NAMESPACE_SCOPE_P. + (lang_decl_name): Likewise. + * pt.c (tsubst_friend_function, tsubst): Likewise. + * decl.c (pushdecl, redeclaration_error_message, start_decl, + cp_finish_decl, start_function): Likewise. + * class.c (finish_struct_1): Likewise. + * call.c (build_over_call): Likewise. + (compare_ics): Use DERIVED_FROM_P. + +Tue May 12 07:24:18 1998 Mark Mitchell + + * cp-tree.h (CANONICAL_TYPE_VARIANT): New macro. + * method.c (build_mangled_name): Use it. + (build_decl_overload_real): Likewise. + + * error.c (dump_simple_decl): New function, broken out from ... + (dump_decl): Use it. + +Mon May 11 11:38:07 1998 Mark Mitchell + + * ptree.c (lang_print_xnode): Add missing `break'. + + * pt.c (tsubst): Remove duplicate check for IDENTIFIER_NODE. + + * call.c (add_template_candidate): Adjust for changes to + fn_type_unification. + (add_template_candidate_real): Likewise. + (add_template_conv_candidate): Likewise. + (build_user_type_conversion_1): Likewise. + (build_new_function_call): Likewise. + (build_object_call): Likewise. + (build_new_op): Likewise. + (build_new_method_call): Likewise. + * class.c (instantiate_type): Likewise. + * cp-tree.h (unification_kind_t): New type. + (fn_type_unification): Adjust prototype. + (type_unificaiton): Likewise. + * pt.c (UNIFY_ALLOW_NONE): New macro. + (UNIFY_ALLOW_MORE_CV_QUAL): Likewise. + (UNIFY_ALLOW_LESS_CV_QUAL): Likewise. + (UNIFY_ALLOW_DERIVED): Likewise. + (unify): Change prototype. + (maybe_adjust_types_for_deduction): New function. + (check_cv_quals_for_unify): Likewise. + (determine_specialization): Adjust. + (fn_type_unification): Likewise. + (type_unification): Likewise. + (type_unification_real): Likewise. Use + maybe_adjust_types_for_deduction. Fix mishandling of + back-unification of template functions passed as arguments. Pass + appropriate combination of UNIFY_ALLOW_* to unify. + (unify): Remove unused NTPARMS parameter. Use + check_cv_quals_for_unify. Remove bogus code that allowed + too-generous unification in order to adhere more closely to standard. + (get_bindings_real): Adjust. + (get_class_bindings): Likewise. + + * method.c (build_overload_identifier): Only use the innermost + template arguments when mangling. + * pt.c (tsubst_template_argument_vector): New function. + (complete_template_args): Deal with the situation where the + extra_args contain more than one level of arguments. + (lookup_template_class): Deal with member template classes, which + may have more than one level of arguments. + (tsubst): Don't tsbust into the TREE_TYPE of an IDENTIFIER_NODE. + Improve handling of member template classes. Use + DECL_PRIMARY_TEMPLATE instead of inline expansion. Use + tsubst_template_argument_vector where appropriate. + (regenerate_decl_from_template): Break out from ... + (instantiate_decl): Here. + + * lex.c (yyprint): Remove TYPENAME_ELLIPSIS. + * parse.h: Regenerated. + * parse.c: Really regenerated. + + * cp-tree.h (finish_unary_op_expr): New function. + (finish_id_expr): Likewise. + (begin_new_placement): Likewise. + (finish_new_placement): Likewise. + (finish_declarator): Likewise. + (finish_translation_unit): Likewise. + (finish_parmlist): Likewise. + (begin_class_definition): Likewise. + (finish_class_definition): Likewise. + (finish_default_args): Likewise. + (finish_inline_definitions): Likewise. + * parse.y (GCC_ASM_KEYWORD): Remove. + (TYPENAME_ELLIPSIS): Likewise. + * parse.c: Regenerated. + Use new functions in semantics.c in the actions for many rules. + * gxx.gperf (GCC_ASM_KEYWORD): Just use ASM_KEYWORD. + * hash.h: Regenerated. + * semantics.c (finish_expr_stmt): Allow NULL expr. + (finish_unary_op_expr): New function, containing + code previously in parse.y. + (finish_id_expr): Likewise. + (begin_new_placement): Likewise. + (finish_new_placement): Likewise. + (finish_declarator): Likewise. + (finish_translation_unit): Likewise. + (finish_parmlist): Likewise. + (begin_class_definition): Likewise. + (finish_class_definition): Likewise. + (finish_default_args): Likewise. + (finish_inline_definitions): Likewise. + +Sun May 10 23:43:13 1998 Mark Mitchell + + * typeck.c (build_c_cast): Don't decay arrays and functions to + pointer type when converting to a class type. + +Sun May 10 22:53:56 1998 Jason Merrill + + * cp-tree.h (DECL_NAMESPACE_SCOPE_P): New macro. + (DECL_CLASS_SCOPE_P): Likewise. + +Sun May 10 22:48:22 1998 H.J. Lu (hjl@gnu.org) + + * class.c (finish_struct_1): Use OVL_CURRENT on TREE_VEC_ELT. + * decl2.c (constructor_name_full): Likewise. + +Sun May 10 22:48:12 1998 Mike Stump + + * tree.c (mapcar): Add OVERLOAD support. + + * init.c (resolve_offset_ref): We must use basetype_path before we + destroy it with a call to convert_pointer_to. + +Sat May 9 14:44:37 1998 Jason Merrill + + * class.c (currently_open_class): New fn. + * decl.c (lookup_name_real): Use it. + * search.c (lookup_field): Likewise. + +Fri May 8 23:32:42 1998 Martin von Loewis + + * cp-tree.def (OVERLOAD): New node. + * cp-tree.h (BINDING_TYPE, SET_IDENTIFIER_GLOBAL_VALUE, + SET_IDENTIFIER_NAMESPACE_VALUE): Define. + (NAMESPACE_BINDING): Remove. + (IDENTIFIER_GLOBAL_VALUE, IDENTIFIER_NAMESPACE_VALUE): Use + namespace_binding. + (OVL_FUNCTION, OVL_CHAIN, OVL_CURRENT, OVL_NEXT, OVL_USED): + Define. + (tree_overload): New struct. + (IDENTIFIER_TYPE_VALUE): Use identifier_type_value. + (REAL_IDENTIFIER_TYPE_VALUE): Define. + (IDENTIFIER_HAS_TYPE_VALUE): Use IDENTIFIER_TYPE_VALUE. + (lang_decl_flags): Remove in_namespace. + (lang_decl): Remove chain. + (DECL_CHAIN, DECL_NAMESPACE): Remove. + (flag_honor_std): Declare extern. + (identifier_type_value, pushdecl_namespace_level, push_using_decl, + namespace_binding, set_namespace_binding, + lookup_function_nonclass, cat_namespace_levels, + set_decl_namespace, lookup_arg_dependent, binding_init, ovl_cons, + scratch_ovl_cons, ovl_member, build_overload): Declare. + (decl_list_length, get_namespace_id, current_namespace_id, + overloaded_globals_p): Remove. + (lookup_using_namespace, qualified_lookup_using_namespace): Change + return type. + (push_scratch_obstack): New macro. + * call.c (add_function_candidate): Special-case type of OVERLOAD node. + (build_user_conversions_1): Iterate using OVL_NEXT for ctors, + convs, fns. + (build_new_function_call): Iterate using OVL_CHAIN. + Print DECL_NAME in when reporting ambiguities. + (build_object_call): Iterate using OVL_NEXT for fns, convs. + (build_new_op): Call lookup_function_nonclass. + Iterate using OVL_NEXT. + (build_op_delete_call): Change detection of members. + Do not wrap TREE_LIST around fields and single global functions. + (build_over_call): Don't push a class level if the context is a + namespace. + (build_new_method_call): Iterate using OVL_NEXT. + * class.c (add_method): Chain overloaded members using + build_overload. Remove copying of method. + (grow_method): When iterating through the obstack, expect OVERLOAD + nodes. Chain overload members. + (finish_struct_methods): Chain overload members. Unpack OVERLOAD + nodes in call to get_baselinks. + (duplicate_tag_error): Expect OVERLOAD nodes when unchaining. + (finish_struct_1): Iterate over ctor using OVL_NEXT. Handle + fdecls that are OVERLOAD nodes. + (validate_lhs): New function. + (instantiate_type): Do not copy OVERLOAD nodes. Remove dead + code. Use DECL_NAME in error messages. Split code between global + and member function processing. + * decl.c (global_type_node): New static variable. + (in_std): New global. + (struct binding_level): New field usings. + (resume_binding_level): Assert that we are not in a class. + (toplevel_bindings_p): Just check for namespace_p or + pseudo_global. + (resume_level): Remove. + (find_binding): New function. + (binding_for_name): Call it. + (namespace_binding, set_namespace_binding): New functions. + (push_namespace): Associate binding level with new namespace, + resume_binding_level for existing namespace. Remove old code. + Fake std by counting. + (store_bindings): Use REAL_IDENTIFIER_TYPE_VALUE. + (maybe_push_to_top_level): Save current namespace. + (pop_from_top_level): Restore saved namespace. + (pop_namespace): Call suspend_binding_level. Remove old code. + (cat_namespace_levels): New function. + (set_identifier_type_value_with_scope): For namespace bindings, + set BINDING_TYPE, and use global_type_node. + Use REAL_IDENTIFIER_TYPE_VALUE otherwise. + (identifier_type_value): New function. + (pushtag): If no context, use current_namespace. + (duplicate_decls): Don't process DECL_CHAIN. + (pushdecl): Set DECL_CONTEXT to current_namespace, if it is not + already set. Never reset it to NULL_TREE. Lookup global variables + in their namespace. Push overloaded templates if they are on + namespace level. + (pushdecl_namespace_level): New function. + (pushdecl_top_level): Implement using pushdecl_namespace_level. + (pushdecl_using_decl): New function. + (overloaded_globals_p): Remove. + (push_overloaded_decl): Create OVERLOAD nodes, and iterate through + them. Use namespace_binding and set_namespace_value. + (redeclaration_error_message): Complain if the declarations come + from different namespaces. + (lookup_tag): On namespace level, look in the BINDING_TYPE. + (lookup_namespace_name): Pass tree_bindings from stack. Remove + old code. + (select_decl): New function. + (lookup_name_real): Call it for qualified and unqualified lookup. + Pass tree_bindings from the stack. + If prefer_type is 1, also accept namespaces. + (lookup_function_nonclass): New function. + (init_decl_processing): Set the binding level of the global + namespace to global_binding_level. + Build a proper type list for __builtin_apply. + Initialize std_node to "fake std" if flag_honor_std is set. + Initialize global_type_node. + Allocated bad_alloc in namespace std if flag_honor_std. + (define_function): Set the DECL_CONTEXT to the current_namespace. + (start_decl): A namespace is not considered as a context here. If + the DECL_CONTEXT is a namespace, push the decl. + (cp_finish_decl): Check for namespaces used as initializers. + (grokfndecl): Add namespace parameter. Remove processing of + DECL_CHAIN. + (grokvardecl): Add namespace parameter. + (grokdeclarator): Process SCOPEs that are namespaces. For + mangling, temporarily set the DECL_CONTEXT on anonymous structs. + (start_function): Check for contexts that are namespaces. + Set context for declarations that have not been pushed. + (store_parm_decls): Check for ::main only. + (finish_function): Likewise. + (start_method): Check for contexts that are namespaces. + (start_method): Remove DECL_CHAIN processing. + * decl2.c (flag_honor_std): Declare. + (lang_decode_option): Set it if -fhonor-std or -fnew-abi is given. + (decl_namespace_list): New static global. + (grok_x_components): Ignore namespaces as type contexts. + (check_classfn): Expect OVERLOAD nodes. + (grokfield): Remove DECL_CHAIN processing. + (finish_file): Call cat_namespace_levels. + (merge_functions): New function. + (ambiguous_decl): Rewrite. + (lookup_using_namespace): Produce tree_bindings. + (qualified_lookup_using_namespace): Likewise. + (set_decl_namespace, decl_namespace, current_decl_namespace, + push_decl_namespace, pop_decl_namespace): New functions. + (arg_lookup): New struct. + (add_function, arg_assoc_namespace, arg_assoc_class, + arg_assoc_type, arg_assoc_args, arg_assoc, lookup_arg_dependent): + New functions. + (get_namespace_id, current_namespace_id): Remove. + (do_toplevel_using_decl): Rewrite. + (do_class_using_decl): Complain about namespace qualifiers. + (do_using_directive): Sorry if not on namespace level. Complain + about unknown namespaces. + * error.c (dump_aggr_type): Check for namespace contexts. + * except.c (init_exception_processing): Push terminate into std. + * friend.c (is_friend): A namespace is not a context, here. + * init.c (expand_member_init): Remove DECL_CHAIN processing. + (build_offset_ref): Process OVERLOAD nodes. + * lang-specs.h (__HONOR_STD): Define if -fnew-abi or -fhonor-std. + * lex.c (identifier_type): Loop using OVL_CHAIN. + (see_typename): Set looking_for_typename to 2. + (real_yylex): Likewise. + (do_identifier): Expect OVERLOAD nodes instead of TREE_LISTs. + (do_scoped_id): Expect OVERLOAD nodes. + Change calling convention for qualified_lookup_using_namespace. + (build_lang_decl): Don't set in_namespace anymore. + * method.c (typevec_size): New global. + (build_overload_nested_name): Return if global_namespace. + Otherwise, always expect a declaration context. + (build_qualified_name): Likewise. + Make sure we don't write beyond typevec_size. + (build_decl_overload_real): Likewise. + Allocate one extra slot for the namespace. + (hack_identifier): Mark code dead. + Process OVERLOAD and NAMESPACE_DECL nodes. + * parse.y (program): Pop namespaces until in global namespace. + (extdef): In a using-declaration, don't discard the identifier if + there is no declaration. + (left_curly): Ignore type contexts which are namespaces. + (typename_sub2): Use IDENTIFIER_TYPE_VALUE to retrieve the type + used as scope. + * pt.c (template_class_depth): Expect types to be namespaces. + (determine_specialization): Simplify by expecting OVERLOAD nodes. + (push_template_decl): Push into namespace level. + Reset ctx if it is a namespace. + Set DECL_CONTEXT to current_namespace if not set already. + Ignore real contexts that are namespaces. + (mangle_class_name_for_template): Skip global_namespace. + Mangle other namespaces as declarations. + (lookup_template_function): Set type of OVERLOAD nodes to unknown. + (lookup_template_class): Push into namespace of context. + If the context is a namespace, set it to global_namespace. + Use id_context for mangling. + (for_each_template_parm): Handle OVERLOAD and NAMESPACE_DECL nodes. + (tsubst_friend_function): Ignore namespace contexts. + Push into namespace level. + (tsubst): Handle NAMESPACE_DECL nodes. + Remove DECL_CHAIN processing. + (type_unification_real): Recognize OVERLOAD instead of TREE_LIST nodes. + * ptree.c (print_lang_identifier): Print bindings. + (lang_print_xnode): Print OVERLOAD nodes. + * rtti.c (init_rtti_processing): Push type_info into std. + * search.c (lookup_fnfields_here): Expect OVERLOAD nodes. + (lookup_fnfields_1, get_virtuals_named_this, get_matching_virtual, + dfs_debug_mark, dfs_pushdecls, dfs_compress_decls, add_conversions, + lookup_fnfields_here): Likewise. + Process all nodes, instead of going through TREE_CHAIN. + * sig.c (build_signature_pointer_or_reference_type): Set context + to global_namespace. + (build_signature_table_constructor): Expect OVERLOAD nodes. + * spew.c (yylex): Save old setting of looking_for_typename. + * tree.c (decl_list_length): Remove. + (binding_init): New function. + (count_functions): Rewrite. + (is_overloaded_fn): Expect OVERLOAD nodes. + (really_overloaded_fn, get_first_fn, lvalue_type): Likewise. + (ovl_cons, scratch_ovl_cons, build_overload, build_overload_after, + ovl_member): New functions. + * typeck.c (require_complete_type): Expect OVERLOAD nodes. + (type_unknown_p): Likewise. + (require_instantiated_type): Likewise. + (build_component_ref): Declare code dead. + (build_x_function_call): Create and expect OVERLOAD nodes. + (build_function_call_real): Check for ::main only. + (build_unary_op): Likewise. Expect OVERLOAD nodes. + (convert_for_assignment): Check for TREE_LIST before accessing + TREE_VALUE. + * decl.c (duplicate_decls): Check for namespace bindings instead + of global bindings. + (pushdecl, push_overloaded_decl, lookup_tag, lookup_name_real, + lookup_name_current_level, start_decl, xref_tag, + finish_enum): Likewise. + * init.c (build_offset_ref): Likewise. + * search.c (lookup_field): Likewise. + (lookup_fnfields): Likewise. + (dfs_debug_mark): Likewise. + * decl.c (poplevel): Use SET_IDENTIFIER_TYPE_VALUE. + (poplevel_class, pop_from_top_level): Likewise. + * decl2.c (finish_method): Likewise. + * class.c (build_vtable): Use SET_IDENTIFIER_GLOBAL_VALUE. + * decl.c (record_builtin_type): Likewise. + (init_decl_processing, grokfndecl): Likewise. + * lex.c (get_time_identifier, do_identifier, do_scoped_id): Likewise. + (make_lang_type): Likewise. + * parse.y (make_thunk): Likewise. + * pt.c (tsubst): Likewise. + * tree.c (debug_binfo): Likewise. + * exception.cc, new.cc, new1.cc, new2.cc, tinfo.cc, tinfo.h, + tinfo2.cc, inc/new.h: Add std qualifications. + * inc/new: Wrap with namespace std if __HONOR_STD. + * inc/typeinfo: Likewise. + +Fri May 8 00:43:50 1998 Jason Merrill + + * call.c (build_user_type_conversion_1): Handle second_conv + properly for templates. + +Thu May 7 17:09:25 1998 Andrew MacLeod + + * method.c (build_decl_overload_real): Set TREE_USED flag to + zero for build_type_variants nodes as well. + +Wed May 6 19:27:09 1998 Jason Merrill + + * pt.c (tsubst): Don't tsubst the type of an IDENTIFIER_NODE. + +Wed May 6 16:49:48 1998 Jim Wilson + + * Makefile.in (call.o, class.o, decl.o, decl2.o, errfn.o, error.o, + except.o, expr.o, friend.o, init.o, lex.o, method.o, pt.o, repo.o, + rtti.o, search.o, semantics.o, sig.o, tree.o, typeck.o, typeck2.o, + xref.o): Add toplev.h dependencies. + +Wed May 6 16:44:58 1998 Jeffrey A Law (law@cygnus.com) + + * errfn.c (cp_error, cp_warning): Remove declarations for + error and warning respectively. + +Wed May 6 14:28:18 1998 Kaveh R. Ghazi + + * error.c: Convert to using ctype macros defined in system.h. + * method.c: Likewise. + * xref.c: Likewise. + * lex.c: Likewise. Also remove redundant system header stuff. + +Wed May 6 06:36:41 1998 Robert Lipe + + * call.c, class.c, decl.c, decl2.c, errfn.c, error.c, except.c, + expr.c, friend.c, init.c, lex.c, method.c, pt.c, repo.c, rtti.c, + search.c, semantics.c, sig.c, tree.c, typeck.c, typeck2.c, + xref.c: Add include of toplev.h. + +Wed May 6 02:33:39 1998 Jason Merrill + + * tree.c (perm_manip): Also regenerate the RTL of an extern. + (copy_to_permanent): Use end_temporary_allocation. + +Tue May 5 23:54:04 1998 Jason Merrill + + * init.c (expand_vec_init): The initialization of each array + element is a full-expression. + +Tue May 5 18:24:13 1998 Andrew MacLeod + + * method.c (build_mangled_name): Add a call to build_type_variant + to get the right type. + +Tue May 5 01:25:03 1998 Jason Merrill + + * Makefile.in: Add .SUFFIXES. + + * cp-tree.def: Remove NAMESPACE_DECL. + +Sun May 3 01:32:14 1998 Jason Merrill + + * call.c (build_over_call): Do evaluate arg even if it has empty + class type. + * decl.c (start_function): Don't push a member function. + +Thu Apr 30 18:59:23 1998 Jim Wilson + + * Makefile.in (g++FAQ.info): Put -o option before input file. + +Thu Apr 30 13:05:33 1998 Andrew MacLeod + + * gxxint.texi: Add info for squangling codes K and B. + +Tue Apr 28 13:22:01 1998 Mark Mitchell + + * semantics.c (begin_stmt_expr): Avoid duplicating the effect of + the expression in templates. + (finish_stmt_expr): Likewise. + +1998-04-28 Brendan Kehoe + + * decl2.c (ambiguous_decl): Fix NAME parm to be a tree, not int. + +Mon Apr 27 13:58:10 1998 Mark Mitchell + + * decl.c (maybe_push_to_top_level): Always clear + current_template_parms and processing_template_decl. + (pushtag): Remove check of current_class_type and some comments, + since maybe_push_to_top_level no longer creates confusion. + +Sun Apr 26 12:10:18 1998 Mark Mitchell + + * cp-tree.h (CLASSTYPE_IS_TEMPLATE): New macro. + (DECL_CLASS_TEMPLATE_P): Likewise. + (DECL_PRIMARY_TEMPLATE): Likewise. + (PRIMARY_TEMPLATE_P): Use it. + (push_template_decl_real): New function. + (redeclare_class_template): Take new template parameters as + input. + (is_specialization_of): New function. + (comp_template_args): Declare. + * decl.c (pushtag): Handle friend template classes. + (xref_tag): Likewise. Use new calling convention for + redeclare_class_template. + * decl2.c (grok_x_components): Handle friend templates. + * friend.c (is_friend): Use is_specialization_of where + appropriate. Deal with friend class templates. + (make_friend_class): Let a class template be friends with itself. + * pt.c (comp_template_args): Remove declaration. + (tsubst_friend_class): New function. + (push_template_decl_real): New function. + (push_template_decl): Use it. + (redeclare_class_template): Adjust for new calling convention. + (comp_template_args): Give it external linkage. + (instantiate_class_type): Use tsubst_friend_class to deal + with friend templates. + * typeck.c (comptypes): Use comp_template_args, rather than + expanding it inline. + * parse.y (component_decl): Handle a nested template type + like other component type declarations. + + * pt.c (check_explicit_specialization): Handle overloaded + constructors correctly. + + * pt.c (mabybe_get_template_decl_from_type_decl): New function. + (lookup_template_class): Use it. + +Thu Apr 23 21:19:06 1998 Jason Merrill + + * cp-tree.def: Add WRAPPER. USER_CONV now only has two ops. + * cp-tree.h: Add WRAPPER support. + * call.c (add_candidate): Split out from add_*_candidate fns. + (build_over_call): Take the candidate instead of function and args. + Enforce access control here. Emit overload warnings here. + (add_warning): New fn. + (joust): Add WARN parm. If not set, call add_warning instead of + printing a warning. Re-enable some warnings. + (tourney): Pass it. + (convert_like): Adjust. + (build_new_op): Adjust. + (build_new_function_call): Adjust. + (build_user_type_conversion_1): Adjust. + (USER_CONV_FN): Adjust. + * tree.c (build_expr_wrapper, build_expr_ptr_wrapper, + build_int_wrapper): New fns. + +Thu Apr 23 18:27:53 1998 Mark P. Mitchell + + * pt.c (unify): Fix typo in previous change. + +Thu Apr 23 09:32:58 1998 Jason Merrill + + * error.c (dump_type_real): Declare canonical_name. + + * typeck.c (comp_target_types): Fix PMFs. + +Wed Apr 22 13:24:48 1998 Mark Mitchell + + * class.c (finish_struct): Set TREE_PRIVATE and TREE_PROTECTED for + the DECL_RESULTs of a member TEMPLATE_DECL, not just the + TEMPLATE_DECL. + + * pt.c (tsubst): Decrease the template-level of + TEMPLATE_TEMPLATE_PARMS. Likewise for the DECL_INITIAL of a + TEMPLATE_PARM_INDEX. + (template_decl_level): New function. + (unify): Make sure to record unifications for template + parameters, even when the parameters exactly match the arguments. + Combine duplicated code for TEMPLATE_TEMPLATE_PARMs and + TEMPLATE_TYPE_PARMS. Don't try to unify template parameters that + aren't from the level we're currently working on. + +Tue Apr 21 22:00:04 1998 Mark Mitchell + + * errfn.c (cp_thing): Use xrealloc, not xmalloc, to copy memory. + + * decl2.c (check_member_template): Set DECL_IGNORED for member + class templates, too. + + * decl2.c (grokfield): Remangle the name of a member TYPE_DECL. + +Tue Apr 21 18:59:11 1998 Benjamin Kosnik + + * decl.c (duplicate_decls): Only check DECL_FRIEND_P if function. + +Tue Apr 21 14:22:00 1998 Jeffrey A Law (law@cygnus.com) + + * cp-tree.h (intTI_type_node, unsigned_intTI_type_node): Declare. + * decl.c (intTI_type_node, unsigned_intTI_type_node): Define. + (init_decl_processing): Handle TI types. + * typeck.c (unsigned_type, signed_type): Handle TI types. + +Sat Apr 18 15:25:21 1998 Jim Wilson + + * g++spec.c (lang_specific_driver): New argument in_added_libraries. + New local added_libraries. Increment count when add library to + arglist. + +Fri Apr 17 21:25:00 1998 Mark Mitchell + + * cp-tree.h (type_as_string_real): New function. + * pt.c (mangle_class_name_for_template): Use it. + * error.c (dump_aggr_type): Change prototype. + (dump_type_prefix): Likewise. + (dump_type_suffix): Likewise. + (dump_type_real): Convert from dump_type. If desired, the + "canonica" name of a typedef, i.e., the name of the underlying + type, can be printed. + (dump_type): Call dump_type_real. + +Fri Apr 17 14:30:45 1998 Jason Merrill + + * decl2.c (lang_decode_option): -fnew-abi implies -fvtable-thunks. + + * typeck.c (comp_target_types): Tweak pedantic case. + (comp_target_parms): Tweak pedantic case. Clean up somewhat. + Return -1 or 1 instead of 1 or 2. + (compparms): Remove STRICT handling. + (convert_for_assignment): Fix handling of pmfs. + +Fri Apr 17 14:04:16 1998 Mark Mitchell + + * typeck.c (comp_target_types): Handle references like pointers. + (comp_target_parms): Note that return code from comp_target_types + can be negative to indicate failure. + +Fri Apr 17 09:10:52 1998 Andreas Schwab + + * Make-lang.in (c++.all.build): Don't depend on $(DEMANGLER_PROG), + which requires a working target compiler to build. + +Fri Apr 17 08:57:35 1998 Jeffrey A Law (law@cygnus.com) + + * tree.c (avoid_overlap): Add prototype. + + * spew.c (num_tokens): Add prototype. + (nth_noken, add_token, consume_token, debug_yychar): Likewise. + + * search.c (dfs_check_overlap): Add prototype. + (dfs_no_overlap_yet): Likewise. + + * pt.c (original_template): Add prototype. + (inline_needs_template_parms): Likewise. + (push_inline_template_parms_recursive): Likewise. + (retrieve_specialization, register_specialization): Likewise. + (print_candidates, reduce_template_parm_level): Likewise. + (build_template_decl, mark_template_parm): Likewise. + (tsubst_friend_function, get_bindings_real): Likewise. + + * method.c (start_squangling): Add prototype. + (end_squangling, check_ktype, issue_ktype): Likewise. + (build_overloaded_scope_ref, check_btype): Likewise. + (build_mangled_template_parm_index): Likewise. + + * lex.c (init_cpp_parse): Add prototype. + (handle_cp_pragma, handle_sysv_pragma): Likewise. + (reduce_cmp, token_cmp): Likewise. + + * except.c (call_eh_info): Add prototype. + (push_eh_info, get_eh_info, get_eh_value, get_eh_type): Likewise. + (get_eh_caught, get_eh_handlers, do_pop_exception): Likewise. + + * decl2.c (is_namespace_ancestor): Add prototype. + (namespace_ancestor, add_using_namespace): Likewise. + (ambiguous_decl): Likewise. + + * decl.c (indent): Add prototype. + + * call.c (add_template_candidate_real): Add prototype. + +Fri Apr 17 01:57:12 1998 Jason Merrill + + * decl2.c (build_expr_from_tree): Just return a PMF. + +Fri Apr 17 00:45:12 1998 Mark Mitchell + + * typeck2.c (process_init_constructor): Don't strip cv-qualifiers + when doing initializations. + + * pt.c (unify): Use comptypes to compare type args. + +Fri Apr 17 00:24:22 1998 Jason Merrill + + * decl.c (duplicate_decls): Fix check for when it's safe to free + the new decl. + + * pt.c (mangle_class_name_for_template): Don't pass a typedef type + to type_as_string. + +Thu Apr 16 17:47:30 1998 Jeffrey A Law (law@cygnus.com) + + * pt.c (build_template_parm_index): Add prototype. + + * search.c (my_tree_cons): Don't clear words outside the + newly allocated node. + +Wed Apr 15 15:34:44 1998 Dave Brolley + + * lex.c (init_parse): Now returns char* containing the filename. + +Wed Apr 15 13:20:06 1998 John Carr + Jeff Law + + * errfn.c: Rework to avoid problems when HOST_WIDE_INT is longer + than a pointer. + +Sun Apr 12 22:31:19 1998 Richard Kenner + + * cvt.c (cp_convert_to_pointer): Use TYPE_PRECISION. + +Fri Apr 10 12:16:49 1998 Benjamin Kosnik + + * decl.c (duplicate_decls): Don't warn for redundant decls if + friend: let add_friend take care of it. + +Thu Apr 9 02:40:48 1998 Jason Merrill + + * sig.c (build_signature_pointer_constructor): Don't set + TREE_HAS_CONSTRUCTOR for a signature pointer. + * cvt.c (ocp_convert): Don't force a temporary for internal structs. + * init.c (resolve_offset_ref): Warn about implicit & on pmfs + here, too. + * typeck.c (build_unary_op): Only allow taking the address of a + real constructor. + * typeck2.c (digest_init): Simplify. + (store_init_value): Don't pedwarn about using { } for pmfs. + +Thu Apr 9 22:16:57 1998 Per Bothner + + * cp-tree.h (start_decl): Update prototype. + * decl.c (start_decl): Like the C version, new parameters + for the attributes. Call cplus_decl_attributes here, + (pushdecl): Like C version, do build_type_copy if TYPE_DECL, + (grokdeclarator): Pass NULL for new start_decl arguments. + * pt.c (tsubst_expr): Likewise. + * parse.y: Merge cplus_decl_attribute calls into start_decl calls. + * typeck.c (common_type): Check TYPE_MAIN_VARIANT. + * lex.c (build_lang_decl): Add lang_name_java. + * class.c (push_lang_context): Add lang_name_java. + * method.c (build_mangled_name): Check for is_java_type. + +Thu Apr 9 22:16:57 1998 Benjamin Kosnik + + * decl.c (grokdeclarator): Check TYPE_MAIN_VARIANT. + * call.c (build_scoped_method_call): Check for TREE_CODE for + VOID_TYPE instead of type == void_type_node. + (build_method_call): Likewise. + * decl.c (lookup_name_real): Likewise. + (grokdeclarator): Likewise. + (start_decl): Likewise. + (grokparms): Likewise. + (start_function): Likewise. + (finish_function): Likewise. + (start_method): Likewise. + +Thu Apr 9 00:18:44 1998 Dave Brolley (brolley@cygnus.com) + + * lex.c (finput): New variable. + (init_cpp_parse): Renamed from init_parse. + (init_parse): Handle !USE_CPPLIB. Call init_cpp_parse when finished. + (finish_parse): New function. + * cp-tree.h (init_lex, init_parse): Remove declarations. + +Mon Apr 6 02:25:05 1998 Jason Merrill + + * call.c (build_call): Still evaluate the actual argument. + * class.c (is_empty_class): Update for -fnew-abi. + + * decl2.c: -fnew-abi implies -fsquangle. + + * method.c (do_build_assign_ref): Don't do anything to copy + an empty class. + (do_build_copy_constructor): Likewise. + * call.c (build_over_call): Likewise. + +Sat Apr 4 18:43:58 1998 Jason Merrill + + * tree.c (avoid_overlap): Return a value. + +Sat Apr 4 12:52:35 1998 Jeffrey A Law (law@cygnus.com) + + * method.c (check_btype): Add missing argument to xrealloc. + (check_ktype): Likewise. + +Fri Apr 3 02:22:59 1998 Jason Merrill + + Implement empty base optimization. + * class.c (finish_struct_1): Add vbase fields earlier. Set + CLASSTYPE_SIZE of an empty base to 0. Types with bases can be empty. + * search.c (dfs_check_overlap, dfs_no_overlap_yet): New fns. + (types_overlap_p): New fn. + * tree.c (avoid_overlap): New fn. + (build_base_fields): Use it to avoid overlapping empty bases. + * cp-tree.h, decl2.c, lang-options.h: Add -fnew-abi. + + * decl.c (cplus_expand_expr_stmt): Strip unused INDIRECT_REFs. + + Re-implement allocation of base class subobjects. + * tree.c (unshare_base_binfos): New fn. + (layout_basetypes): Use it. Now handles offsets of both virtual and + non-virtual bases, after layout_type. + (layout_vbasetypes): Remove. + (build_base_fields): Generate FIELD_DECLs for each non-virtual base. + (build_vbase_pointer_fields): Split out from old layout_basetypes. + * class.c (finish_base_struct): Lose offset handling code. + Move nonvdtor warning here. Don't mess with t_binfo anymore. + (finish_struct_1): Don't mess with t_binfo anymore. Use fns above. + * cp-tree.h: Adjust. + +Thu Apr 2 14:25:13 1998 Jason Merrill + + * cp-tree.h: Lose CLASSTYPE_VBASE_SIZE, some unused stuff. + * decl.c, decl2.c, pt.c, ptree.c, lex.c: Likewise. + * class.c (duplicate_tag_error): Likewise. + (finish_struct_1): Set CLASSTYPE_SIZE, CLASSTYPE_MODE, CLASSTYPE_ALIGN. + * tree.c (layout_vbasetypes): Update from layout_record, remove + var_size support, use CLASSTYPE_SIZE instead of CLASSTYPE_VBASE_SIZE. + (layout_basetypes): Likewise. + +Wed Apr 1 18:22:25 1998 Jeffrey A Law (law@cygnus.com) + + * class.c, Make sure system.h is included just after config.h. + Delete lingering stdio and errno references too. + * decl.c, errfn.c, parse.y, ptree.c search.c, xref.c: Likewise. + +Wed Apr 1 15:38:36 1998 Jason Merrill + + * friend.c (is_friend): Fix access control for local classes. + + * class.c (is_empty_class): New fn. + * call.c (build_call): Don't pass empty class objects to a function. + +Wed Apr 1 14:58:35 1998 Mark Mitchell + + * call.c (build_over_call): Do name resolution for default + arguments of function templates in the scope of the templates. + +Tue Mar 31 13:43:57 1998 Jeffrey A Law (law@cygnus.com) + + * call.c: Include system.h. Remove includes, declarations and + defines provided by system.h. + * class.c, cvt.c, decl.c, decl2.c, errfn.c error.c: Likewise. + * except.c, expr.c friend.c, g++spec.c, init.c, input.c: Likewise. + * lex.c, parse.y, pt.c, ptree.c repo.c rtti.c, search.c: Likewise. + * semantics.c, sig.c, spew.c, tree.c, typeck.c: Likewise. + * typeck2.c, xref.c: Likewise. + * Makefile.in: Dependencies updated as appropriate. + * Make-lang.in: Likewise. + +Mon Mar 30 12:15:00 1998 Mark Mitchell + + * pt.c (fn_type_unification): Allow incomplete unification without + an immediate error message. + +Mon Mar 30 08:55:42 1998 Jason Merrill + + * tree.c (member_p): New fn. + * decl2.c (finish_file): Only set DECL_STATIC_FUNCTION_P for + initializing class members. + + * cp-tree.def (TEMPLATE_PARM_INDEX): Class 'x'. + * ptree.c (lang_print_xnode): Handle TEMPLATE_PARM_INDEX. + + * call.c (build_method_call): Handle non-scoped destructors, too. + * pt.c (tsubst_copy): Likewise. + + * pt.c (print_template_context): Split out... + (push_tinst_level): ...from here. + + * friend.c (is_friend): Don't pass a type to decl_function_context. + + * typeck.c (convert_for_initialization): Always hand off + conversions to class type. + +Sun Mar 29 20:01:59 1998 Jason Merrill + + * friend.c (is_friend): Local classes have the same access as the + enclosing function. + +Sun Mar 29 00:47:32 1998 Jeffrey A Law (law@cygnus.com) + + * typeck.c (expand_target_expr): Delete dead function. + + * search.c: Put various prototypes inside #ifdef MI_MATRIX. + + * repo.c (save_string): Delete dead function. + + * method.c (thunk_printable_name): Delete dead function. + + * lex.c (yynextch): Delete dead function. + + * expr.c (tree_extract_aggr_init): #if 0 out. + + * except.c (do_unwind): Delete dead function. + (easy_expand_asm): Likewise. + + * cvt.c (build_conversion_type_1): Delete dead function. + + * cp-tree.h (push_expression_obstack): Declare. + + * call.c (source_type): #if 0 out. + + * class.c (alter_access): Remove unused label. Add braces + around empty else clause. + + * lex.c (yyprint): Fix argument to printf. + +Sat Mar 28 17:43:52 1998 Mark Mitchell + + * pt.c (tsubst): Clear TREE_USED for new FUNCTION_DECLs. + + * pt.c (instantiate_class_template): Make sure template + arguments are permanent. + * init.c (resolve_offset_ref): Don't go looking around in + template types. + + * semantics.c: Add routines to handle expressions, and some + declaration processing. + * parse.y: Use them. + (current_class_depth): Move declaration to cp-tree.h. + * parse.c: Regenerated. + * cp-tree.h: Use them. + (current_class_depth): Declare. + * pt.c (tsubst_copy): Use begin_stmt_expr and finish_stmt_expr. + +Fri Mar 27 20:23:18 1998 Mark Mitchell + + * error.c (dump_decl): Be a bit more explicit with template + type arguments, when verbose. + +Fri Mar 27 18:16:40 1998 Jason Merrill + + * inc/exception: Reorder closing braces. + +Fri Mar 27 13:22:18 1998 Mark Mitchell + + * pt.c (redeclare_class_template): New function. + * cp_tree.h (redeclare_class_template): Declare it. + * decl.c (xref_tag): Use it. + +Thu Mar 26 11:16:30 1998 Jason Merrill + + * call.c (build_over_call): Check IS_AGGR_TYPE, not + TYPE_LANG_SPECIFIC. + * typeck.c (convert_arguments): Likewise. + + * decl.c (grokdeclarator): Remove const and volatile from type after + setting constp and volatilep. + + * class.c (finish_struct_1): Don't warn about bool bitfield larger + than one bit. + +Thu Mar 26 10:25:52 1998 Mark Mitchell + + * pt.c (convert_nontype_argument): STRIP_NOPS where appropriate. + +Thu Mar 26 10:24:05 1998 Mark Mitchell + + * call.c (build_object_call): Complain about ambiguous operator(), + rather that crashing. + (build_new_op): Likewise. + (build_op_delete_call): Likewise. + +Thu Mar 26 10:23:24 1998 Mark Mitchell + + * cvt.c (perform_qualification_conversions): Use comp_target_types + instead of comp_ptr_ttypes. + +Wed Mar 25 16:10:50 1998 Mark Mitchell + + * cp-tree.h (enforce_access): Declare. + * call.c (enforce_access): Make it extern, not static. + * class.c (alter_access): Use enforce_access; modify code for ISO + compliance, rather than ARM rules. + +Wed Mar 25 12:10:45 1998 Kriang Lerdsuwanakij + + * cp-tree.h: Fix typo. + +Wed Mar 25 02:01:02 1998 Jason Merrill + + * expr.c (cplus_expand_expr): Only do PCC_STATIC_STRUCT_RETURN thing + if (aggregate_value_p (type)). + + * decl2.c (constructor_name_full): Handle TYPENAME_TYPE. + +Tue Mar 24 16:12:01 1998 Mark Mitchell + + * tree.c (mapcar): When dealing with a DECL, use it's constant + value, if any. + * pt.c (lookup_template_class): Don't mangle the names of template + classes whose arguments are unknown. + + * pt.c (tsubst_expr): Handle GOTO_STMT correctly. + +Tue Mar 24 12:21:55 1998 Benjamin Kosnik + + * decl.c (init_decl_processing): Set TYPE_PRECISON for bools to 1. + +Tue Mar 24 12:21:48 1998 Jim Wilson + + * decl.c (init_decl_processing): Initialize TYPE_MAX_VALUE for + boolean_type_node to 1. + +Tue Mar 24 10:23:47 1998 Mark Mitchell + + * error.c (dump_expr): Remove unused variable `l'. + + * pt.c (for_each_template_parm): New function, created by + converting uses_template_parms. + (tree_fn_t): New typedef. + (uses_template_parms): Use it. + (mark_template_parm): New function. + (push_template_decl): Check that the argument list of a partial + specialization uses all the template parameters. + + * Make-lang.in (c++filt): Don't delete cxxmain.c after we're done + with it; we might want it for debugging. + * cp-tree.h (type_unification): Change interface. + * class.c (finish_struct_1): Skip nested template types, just like + ordinary nested types. + (instantiate_type): Use new interface to type_unification. + * lex.c (init_lex): Add __sz as opname for sizeof. + * method.c (build_overload_scope_ref): New function. + (build_overload_int): Handle complex expressions. Set + numeric_output_need_bar if necessary. + (build_overload_value): Handle non-PARM_DECL nodes; this + routine is now used by build_overload_int. Remove some + assignments to numeric_output_need_bar. Use + build_overload_scope_ref. + (build_qualified_name): Note that some template mangled names end + with digits, and set numeric_output_need_bar appropriately. Use + build_underscore_int. + * pt.c (unify): Change interface. + (type_unification_real): Likewise. + (determine_specialization): Use new interfaces. + (tsubst): Deal gracefully with situations in which the argument + vector is not fully filled. + (fn_type_unification): Use new interfaces. + (type_unification): Likewise. Remove NOP_EXPR hack. + (type_unification_real): Likewise. + (unify): Likewise. Deal with unification of complex expressions. + +Mon Mar 23 12:24:37 1998 Jason Merrill + + * pt.c (complete_template_args): Initialize skip properly. + + * decl.c (make_typename_type): Revert. + (make_implicit_typename): Remove. + (lookup_name_real): Don't call it. Call lookup_field if we see a + TYPE_DECL from a template base. + * search.c (lookup_field): Do implicit typename stuff. + +Sun Mar 22 00:50:42 1998 Nick Clifton + Geoff Noer + + * Makefile.in: Various fixes for building cygwin32 native toolchains. + * Make-lang.in: Likewise. + +Fri Mar 20 18:07:39 1998 Kriang Lerdsuwanakij + + * pt.c (tsubst, TEMPLATE_TEMPLATE_PARM): Simplify. + +Fri Mar 20 10:42:07 1998 Jason Merrill + + * decl.c (make_implicit_typename): Rewrite removed code. + (make_typename_type): Call it if the type we look up comes from + a base that uses template parms. + + * pt.c (complete_template_args): Rewrite. + (tsubst, FUNCTION_DECL): Use it. + +Fri Mar 20 08:12:43 1998 H.J. Lu (hjl@gnu.org) + + * semantics.c (finish_asm_stmt): Fix combine strings. Call + c_expand_asm_operands () if output_operands, input_operands or + clobbers is not NULL_TREE. + +Fri Mar 20 00:10:19 1998 Kriang Lerdsuwanakij + + * pt.c (complete_template_args): New function. + (get_bindings): Deal with specializations of function templates + with return type containing parameters from outer class + templates. + (tsubst, TEMPLATE_TEMPLATE_PARM): When reducing parameter level, + substitute arguments and compose a new type. + +Thu Mar 19 19:01:48 1998 Mark Mitchell + + * pt.c (tsubst): Clear DECL_PENDING_INLINE_INFO for new + FUNCTION_DECLs. + +Thu Mar 19 11:51:58 1998 Jason Merrill + + * decl.c (make_implicit_typename): Lose useless code. + + * call.c (standard_conversion): Handle A* -> const A* properly. + + * pt.c (get_bindings_real): Rename from get_bindings. Add + check_rettype parm. + (get_bindings): Pass 1. + (get_bindings_overload): Pass 0. + +Wed Mar 19 09:08:12 1998 Mark Mitchell + + * pt.c (check_explicit_specialization): When reverting a static + member function, also remove the `this' parameter from + last_function_parms. + +Thu Mar 19 02:27:48 1998 Jason Merrill + + * pt.c (tsubst_copy, CONST_DECL): Don't bother tsubsting + a function context. + + * decl.c (store_bindings): Use free_binding_vecs. + (pop_from_top_level): Likewise. + +Wed Mar 18 12:41:43 1998 Jason Merrill + + * decl.c (make_implicit_typename): Only change the type of a + TYPENAME_TYPE. + +Wed Mar 18 10:09:51 1998 Mark Mitchell + + * semantics.c: New file, containing routines to perform the + semantic phase of parsing. + * parse.y: Use it. + * pt.c (tsubst_expr): Likewise. + * cp-tree.h: Declare the various functions in semantics.c. + Provide macros to access _STMT tree nodes. + * cp-tree.def: Add ASM_STMT tree node. + * Makefile.in, Make-lang.in: Add dependencies on and for + semantics.c. + +Wed Mar 18 00:24:10 1998 Jason Merrill + + * pt.c (push_template_decl): Only check primary templates. + + * pt.c (check_explicit_specialization): Complain about default args + in explicit specialization. + + * parse.y (nomods_initdcl0): Also call cp_finish_decl for a + constructor_declarator. + +Tue Mar 17 14:44:54 1998 Mark Mitchell + + * typeck2.c (build_x_arrow): Don't crash when an aggregate type + has no overloaded operator ->. + + * call.c (build_field_call): Don't crash when presented with a + field that is actually a nested type. + + * decl.c (pushtag): Deal with friend class injection in local + classes. + + * call.c (build_object_call): Don't crash if OBJ is a + pointer-to-member-function. + +Tue Mar 17 11:40:26 1998 Jason Merrill + + * pt.c (push_template_decl): Complain about template with C linkage, + anonymous template class. + +Mon Mar 16 12:10:39 1998 Jason Merrill + + * class.c (pushclass): Only use the mi_matrix stuff #ifdef MI_MATRIX. + * search.c: Likewise. + + * lex.c (do_pending_defargs): Only call + maybe_{begin,end}_member_template_processing for FUNCTION_DECLs. + + * parse.y (initdcl0_innards): Move maybeasm back into initdcl0 et al. + +Mon Mar 16 10:47:22 1998 Mark Mitchell + + * parse.y: Deal with CONSTRUCTORS in new_initializers. + +Mon Mar 16 10:54:21 1998 Mark Mitchell + + * pt.c (tsubst_copy): Deal with BIND_EXPR in a way that more + closely mimics the behavior in parse.y. + (tsubst_expr): Return the resulting BLOCK when making a tsubst'ing + into a compound statement. + +Sun Mar 15 02:07:26 1998 Jason Merrill + + * cp-tree.h (TEMPLATE_PARMS_FOR_INLINE): New macro. + * pt.c (inline_needs_template_parms): New fn. + (original_template): New fn. + (push_inline_template_parms_recursive): New fn. + (maybe_begin_member_template_processing): Use them. + (maybe_end_member_template_processing): Likewise. + (is_member_or_friend_template): Rename to is_member_template. + Member functions of local classes are never member templates. + +Sun Mar 15 01:14:22 1998 Kriang Lerdsuwanakij + + * lex.c (do_identifier): Handle TEMPLATE_DECL that was + added in the class scope to catch redefinition error. + + * pt.c (reduce_template_parm_level): Also copy + the DECL_TEMPLATE_PARMS field. + +Sun Mar 15 10:54:08 1998 Mark Mitchell + + * pt.c (tsubst): Clear TYPE_REFERENCE_TO when creating a + reduced-level template type parameter. + +Sun Mar 15 12:26:02 1998 Manfred Hollstein + + * cp-tree.h (struct lang_decl_flags): Add needs_final_overrider. + (DECL_NEEDS_FINAL_OVERRIDER_P): New macro. + * class.c (override_one_vtable): Set DECL_NEEDS_FINAL_OVERRIDER_P. + * decl.c (duplicate_decls): Propagate it. + * typeck2.c (abstract_virtuals_error): Use two loops to emit + abstract virtual functions and virtual functions which need a + final overrider separately. + +Thu Mar 12 09:39:40 1998 Manfred Hollstein + + * lang-specs.h: Properly put brackets around array elements in + initializer. + + * typeck.c (build_binary_op_nodefault): Correctly place parens around + && and || in expression. + +Thu Mar 12 09:26:04 1998 Manfred Hollstein + + * call.c (default_parm_conversions): Remove prototype definition. + (build_method_call): Remove unused variable result. + + * cvt.c (ocp_convert): Remove unused variable conversion. + + * decl2.c (ambiguous_decl): Add explicit parameter definition for name. + + * except.c (do_unwind): #if 0 definition of unused variables fcall + and next_pc. + + * expr.c (extract_scalar_init): #if 0 prototype and function + definition. + + * init.c (expand_aggr_init_1): Remove unused variable init_type. + (build_new_1): Remove unused variable t. + + * pt.c (instantiate_class_template): Remove unused variable newtag; + cast called function return value to void. + (do_decl_instantiation): Remove unused variables name and fn. + + * tree.c (get_type_decl): Add default return to shut up compiler from + complaining control reaches end of non-void function. + + * typeck.c (build_x_conditional_expr): Remove unused variable rval. + +Thu Mar 12 09:12:15 1998 Manfred Hollstein + + * call.c (default_parm_conversions): Remove prototype definition. + (build_method_call): Remove unused variable result. + (build_over_call): Add default case in enumeration switch. + +Thu Mar 12 08:39:13 1998 Manfred Hollstein + + * decl2.c (lang_decode_option): Change j's type to size_t. + + * tree.c (layout_vbasetypes): record_align and desired_align are of + type unsigned int; const_size and nonvirtual_const_size likewise. + +Wed Mar 11 07:25:20 1998 Mark Mitchell + + * parse.y (new_initializer): Make sure all initializers are + lists. + +Tue Mar 10 07:32:36 1998 Mark Mitchell + + * decl2.c (import_export_decl): Mark tinfo functions for + cv-qualified versions of class types as DECL_NOT_REALLY_EXTERN. + +Fri Mar 6 23:27:35 1998 Jeffrey A Law (law@cygnus.com) + + * method.c: Fix typo. + +Fri Mar 6 10:06:59 1998 Kaveh R. Ghazi + + * method.c: Include "system.h" to get stdlib.h, stdio.h, + ctype.h, string.h, etc. + (issue_nrepeats): Add default case in enumeration switch. + (check_btype): Likewise. + (process_overload_item): Likewise. + + * Makefile.in (method.o): Depend on system.h. + +Wed Mar 4 22:26:53 1998 Andreas Schwab + + * lex.c (do_scoped_id): Fix parenthesizing. + +Wed Mar 4 12:11:53 1998 Michael Tiemann + + * rtti.c (get_tinfo_fn_dynamic): If this function is called an + FLAG_RTTI is unset, initialize type info machinery and continue + with FLAG_RTTI enabled. + (get_typeid): Likewise. + +Wed Mar 4 11:47:55 1998 Jason Merrill + + * typeck.c (unary_complex_lvalue): &D::i has type B::* if i comes + from B. + +Wed Mar 4 11:28:08 1998 Mark Mitchell + + * pt.c (finish_member_template_decl): Deal more gracefully with + invalid declarations. + +Tue Mar 3 01:38:17 1998 Jason Merrill + + * cvt.c, decl.c, decl2.c, init.c, rtti.c, typeck.c, typeck2.c, + cp-tree.h: Clean up more old overloading code, old RTTI code, and + some formatting quirks. + + * call.c, class.c, cp-tree.h, cvt.c, decl.c, init.c, lex.c, + method.c, pt.c, ptree.c, typeck.c: Remove support for + -fno-ansi-overloading and overloading METHOD_CALL_EXPR. + * class.h: Remove. + * Makefile.in: Adjust. + + * pt.c (unify): Don't allow reduced cv-quals when strict. + + * call.c, class.c, pt.c, cp-tree.h: Remove nsubsts parm from + *type_unification* and unify. + +Mon Mar 2 12:11:06 1998 Jason Merrill + + * parse.y (explicit_template_type): Remove TEMPLATE keyword. + (nested_name_specifier): And add it before this use. + (typename_sub0): And this use. Also add use without the keyword. + (typename_sub1): Likewise. + * pt.c (instantiate_class_template): Don't actually instantiate + anything if our type uses template parms. + +Mon Mar 2 11:04:59 1998 Jim Wilson + + * decl.c (start_function): Don't call temporary_allocation for a + nested function. + +Sun Mar 1 21:06:37 1998 Jason Merrill + + * pt.c (instantiate_class_template): Don't mess with friends if + our type uses template parms. + +Sat Feb 28 12:06:44 1998 Jason Merrill + + * parse.y (nested_name_specifier): Use explicit_template_type. + (typename_sub): Allow a template_type, an explicit_template_type, + or an implicit template type at the end. + * lex.c (yyprint): Handle a PTYPENAME being a TEMPLATE_DECL. + * decl.c (make_typename_type): Handle template-id where the name + is a TEMPLATE_DECL. + * call.c (build_scoped_method_call): Handle member template + destructor call. + * pt.c (tsubst_copy, METHOD_CALL_EXPR): Don't assume a member + destructor is represented by the type. + + * cp-tree.h (TYPENAME_TYPE_FULLNAME): New macro. + * parse.y (nested_name_specifier): Add 'template' case. + (explicit_template_type): New rule. + (typename_sub): Use it. + * decl.c (make_typename_type): Handle getting a template-id for NAME. + * pt.c (tsubst): Likewise. + +Fri Feb 27 11:17:50 1998 Jason Merrill + + * pt.c (add_to_template_args): Fix thinko. + (instantiate_class_template): Call it later. + + * pt.c (get_class_bindings): Add outer_args parm. + (most_specialized_class): Likewise. + (instantiate_class_template): Pass it. + (more_specialized_class): Likewise. + (lookup_template_class): Get context from template if none + was specified. + (finish_member_template_decl): Don't do anything with a + partial specialization. + * decl2.c (check_member_template): Use IS_AGGR_TYPE instead of + AGGREGATE_TYPE_P. + * class.c (finish_struct): Member class templates have already been + checked for name clashes. + * decl.c (pushdecl_with_scope): Handle pushing at class level. + +Fri Feb 27 02:25:16 1998 Jason Merrill + + * pt.c (tsubst, TEMPLATE_DECL): Support member class templates. + (tsubst, *_PARM): Support multiple levels of template classes. + (instantiate_class_template): Look up the pattern from the + original template. + (lookup_template_class): Handle getting a template for d1. + (push_template_decl): Correct setting of 'primary'. + (reduce_template_parm_level): Add 'levels' parm. + (finish_member_template_decl): Support member class templates. + (template_class_depth): Handle multiple levels. + * parse.y (component_decl_1, fn.def2): Remove member template case. + (component_decl): Add member template cases. + * decl2.c (check_member_template): We now handle member template + classes. + * decl.c (pushtag): Handle member templates. + * method.c (do_inline_function_hair): Don't touch + IDENTIFIER_GLOBAL_VALUE. + * init.c (build_offset_ref): If name isn't an identifier, just + return it. + * spew.c (yylex): Handle PTYPENAME like TYPENAME. + + * typeck.c (get_delta_difference): Do adjust for conversions to + and from virtual base. + +Wed Feb 25 09:51:29 1998 Jason Merrill + + * typeck.c (get_delta_difference): Give hard error for conversion + from virtual base. + + * cp-tree.h: Tweak formatting. + +Wed Feb 25 00:35:33 1998 Jason Merrill + + * decl.c (push_namespace): Handle redeclaration error. + + * cp-tree.h (IDENTIFIER_NAMESPACE_VALUE): New macro. + (IDENTIFIER_NAMESPACE_BINDINGS): New macro. + (NAMESPACE_BINDING): New macro. + (IDENTIFIER_GLOBAL_VALUE): Use NAMESPACE_BINDING. + * *.c: Use them. + + * pt.c (push_template_decl): Use innermost_args. + + * decl.c (get_unique_name): Tweak from earlier in the name. + +Tue Feb 24 22:15:04 1998 Martin von Loewis + + * cp-tree.def: Add CPLUS_BINDING node. + * cp-tree.h (tree_binding): New struct. + (BINDING_SCOPE, BINDING_VALUE): New macros. + (current_namespace, global_namespace): Declare extern. + (struct lang_decl_flags): New field in_namespace. + (DECL_NAMESPACE_USING, DECL_NAMESPACE_USERS): New macros. + (DECL_NAMESPACE, SET_DECL_NAMESPACE): New macros. + (TREE_INDIRECT_USING): New macro. + * decl2.c (current_namespace, global_namespace): Declare. The + value is a NAMESPACE_DECL now, not a TREE_LIST. + (is_namespace_ancestor, namespace_ancestor): New static functions. + (add_using_namespace, ambiguous_decl): Likewise. + (lookup_using_namespace): New support function for lookup_name. + (qualified_lookup_using_namespace): New support function for + do_scoped_id and lookup_namespace_name. + (get_namespace_id): Mark as obsolete. + (current_namespace_id): Likewise. + (do_namespace_alias): Implement. + (do_using_directive): Implement as call to add_using_namespace. + * decl.c (binding_for_name): New function. + (push_namespace, pop_namespace): Implement. + (push_decl): Don't install a FUNCTION_DECL in the global branch. + (lookup_namespace_name): Implement using qualified lookup. + (lookup_name_real): For global scoping, lookup in + global_namespace. For namespace scoping, lookup in given + namespace. For unscoped lookup, iterate over namespace, + considering using directives. + (init_decl_processing): Initialize global_namespace. + (grokvardecl): Build assembler name as static name for globals. + (grokdeclarator): Remove old namespace mangling. + (xref_tag): When installing a global binding for the + tag, make sure we have an identifier. + * method.c (build_overload_nested_name): Mangle namespaces. + (build_qualified_name): Likewise. + (build_decl_overload_real): Likewise. + * lex.c (build_lang_decl): Set namespace for new declaration to + current_namespace. + (do_scoped_id): Find global names in global or current + namespace, or using qualified namespace lookup, depending on + context. + * init.c (build_member_call): When scope is namespace, use + build_x_function_call instead. + (build_offset_ref): When scope is namespace, collapse processing + to lookup_namespace_name instead. + * error.c (dump_decl): Support NAMESPACE_DECL. + * decl.c (pushdecl): Bind globals to current namespace. + (push_overloaded_decl): Likewise. + (lookup_tag): Likewise. + (lookup_name_current_level): Likewise. + (xref_tag): Likewise. + (start_function): Likewise. + * lex.c (do_identifier): Likewise. + (identifier_typedecl_value): Likewise. + (real_yylex): Likewise. + * method.c (do_inline_function_hair): Likewise. + * parse.y (unscoped): Likewise. + * pt.c (check_explicit_specialization): Likewise. + (lookup_template_class): Likewise. + * rtti.c (call_void_fn): Likewise. + * sig.c (build_sigtable): Likewise. + * ptree.c (lang_print_xnode): New function. + +Tue Feb 24 01:40:24 1998 Jason Merrill + + * pt.c (instantiate_class_template): Don't instantiate if pedantic + and the args use template parms. + + * pt.c (push_tinst_level): If the instantiation uses template parms, + fail silently. + * decl.c (xref_basetypes): Do call complete_type for basetypes + that involve template parameters. + +Tue Feb 24 00:36:43 1998 Jason Merrill + + * typeck2.c (process_init_constructor): Fix labeled init check. + +Mon Feb 23 05:08:55 1998 Jason Merrill + + * pt.c, call.c, decl.c, method.c, cp-tree.h: Remove unused NARGS + argument to tsubst and friends. + + * pt.c (tsubst, FUNCTION_DECL): Tidy. + + * typeck.c (build_x_function_call): Handle static member function + templates like non-templates. Handle friend templates like normal + function templates. + * pt.c (tsubst, *_PARM): Don't use orig_level. + (get_bindings): Don't call add_to_template_args. + (instantiate_template): Likewise. + (tsubst, FUNCTION_DECL): Call add_to_template_args as appropriate. + * ptree.c (print_lang_type): Print index/level for template parms. + +Mon Feb 23 02:52:29 1998 Mark Mitchell + + * Make-lang.in (cc1plus): Note that cc1plus depends on + cp/cp-tree.h and cp/cp-tree.def. + + * cp-tree.def (TEMPLATE_CONST_PARM): Remove. + (TEMPLATE_PARM_INDEX): New tree code, used to indicate a + position in a template parameter list. + * cp-tree.h (template_parm_index): New structure, used as the tree + structure for a TEMPLATE_PARM_INDEX. + (TEMPLATE_PARM_IDX): New macro. + (TEMPLATE_PARM_LEVEL): Likewise. + (TEMPLATE_PARM_DESCENDANTS): Likewise. + (TEMPLATE_PARM_ORIG_LEVEL): Likewise. + (TEMPLATE_PARM_DECL): Likewise. + (TEMPLATE_TYPE_PARM_INDEX): Likewise. + (TEMPLATE_TYPE_ORIG_LEVEL): Likewise. + (TEMPLATE_TYPE_DECL): Likewise. + (TEMPLATE_CONST_IDX): Remove. + (TEMPLATE_CONST_LEVEL): Likewise. + (TEMPLATE_CONST_SET_INFO): Likewise. + (TEMPLATE_TYPE_SET_INFO): Likewise. + (TEMPLATE_TYPE_IDX): Redefine in terms of TEMPLATE_PARM_INDEX + node. + (TEMPLATE_TYPE_LEVEL): Likewise. + * decl.c (decls_match): Call comp_template_parms, rather than + expanding it inline. + (duplicate_decls): If two template declarations are being merged, + then their TEMPLATE_INFOs should be merged as well. + (grokfndecl): Save template-id information when declaring a friend + with explicit template arguments. Pass arguments to + check_explicit_specialization via correct convention; at some + point check_explicit_specialization changed, but these call-sites + did not. + (grokdeclarator): Tidy up slightly. + * decl2.c (check_classfn): Tidy up slightly. Don't assume that + two template functions with the same DECL_ASSEMBLER_NAME the same, + since the names are not yet mangled. + * error.c (dump_decl): Use TEMPLATE_PARM_INDEX instead of + TEMPLATE_CONST_PARM. + (dump_expr): Likewise. Use the TEMPLATE_PARM_DECL to get at the + decl for a non-type parameter, rather than printing `'. + * friend.c (is_friend): Handle TEMPLATE_DECL friends. + (do_friend): Deal with template friends. + * lex.c (do_pending_inlines): Call + maybe_begin_member_template_processing, rather than + conditionally calling begin_member_template_processing. + (process_next_inline): Likewise. Call + maybe_end_member_template_processing, rather than + conditionally calling end_member_template_processing. + (do_pending_defargs): Likewise. + (do_identifier): Use TEMPLATE_PARM_INDEX instead of + TEMPLATE_CONST_PARM. + * method.c (build_mangled_template_parm_index): New function. + (build_overload_value): Use it. + (build_overload_name): Likewise. + * pt.c (finish_member_template_decl): Allow friend declarations. + (template_class_depth): New function. + (is_member_template): Rename, and modify, to become... + (is_member_or_friend_template): New function. + (end_member_template_processing): Rename, and modify, to become... + (maybe_end_member_template_processing). + (build_template_parm_index): New function. + (reduce_template_parm_level): New function. + (process_template_parm): Modify to use build_template_parm_index. + (push_template_decl): Deal with friend templates. + (uses_template_parms): Use TEMPLATE_PARM_INDEX instead of + TEMPLATE_CONST_PARM. + (tsubst_friend_function): New function. + (instantiate_class_template): Generate the DECL_FRIENDLIST + for a new instantiation by using tsubst_friend_function rather + than just tsubst. + (tsubst): Don't tsubst into a type which is a TEMPLATE_DECL. + Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM, and the + appropriate new macros. Use reduce_template_parm_level to + generate lower-level template parameters. Handle tsubst'ing into + TEMPLATE_DECLS that declare TEMPLATE_TEMPLATE_PARMS. Don't forget + to tsubst the DECL_CONTEXT and DECL_CLASS_CONTEXT of newly created + templates. Similarly for the template parameters for a new + template. + (tsubst_copy): Tidy up slightly. Use TEMPLATE_PARM_INDEX instead + of TEMPLATE_CONST_PARM. Handle TYPE_DECLs by tsubsting into them. + (unify): Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM. + (get_bindings): Call add_to_template_args if necessary. + (instantiate_decl): Handle instantiations of friend templates. + * search.c (lookup_field_1): Don't treat the TYPE_FIELDS of a + TEMPLATE_TYPE_PARM as a list of fields; it's not! + * spew.c (yylex): Do a little manual constant propagation to + clarify the code. + +Sun Feb 22 19:53:29 1998 Jeffrey A Law (law@cygnus.com) + + * error.c: Include sys/types.h. + +Thu Feb 19 14:49:09 1998 Jeffrey A Law (law@cygnus.com) + + * method.c (build_mangled_name): Start CPP directives in column zero. + +Thu Feb 19 10:36:48 1998 Jason Merrill + + * typeck2.c (process_init_constructor): Sorry about non-trivial + labeled initializers. + * parse.y (initlist): Re-enable labeled initializers. + +Thu Feb 19 10:15:55 1998 Kriang Lerdsuwanakij + + * pt.c (coerce_template_parms): Add a new parameter, is_tmpl_parm, + all callers changed. Rely on the new parameter instead of arg + being a TREE_LIST when determine whether we are working inside + template template parameter. Clean up is_type test. + +Thu Feb 19 10:04:12 1998 Jason Merrill + + * cvt.c (cp_convert_to_pointer): Preserve TREE_CONSTANT. + * typeck2.c (initializer_constant_valid_p): Allow conversions + between pointers and references. + +1998-02-19 Brendan Kehoe + + * typeck.c (build_unary_op): Only warn about incr/decr a pointer + if pedantic || warn_pointer_arith. + +Thu Feb 19 09:37:21 1998 Kriang Lerdsuwanakij + + * pt.c (unify): Handle TEMPLATE_DECL. + +1998-02-18 Brendan Kehoe + + * cp-tree.h (strip_attrs): Remove decl. + +1998-02-18 Doug Evans + + * decl.c (duplicate_decls): Call merge_machine_decl_attributes. + Update olddecl's attributes too. + (strip_attrs): Remove function. + * typeck.c (common_type): Call merge_machine_type_attributes. + +Tue Feb 17 14:07:52 1998 Mark Mitchell + + * parse.y (initdcl0_innards): New grammar symbol. + (nomods_initdecls, nomods_initdcl0): Change type from itype to + none, since the resulting value is never used. + (parse_decl): New function. + (datadef): Remove redundant actions. + (initdcl0, notype_initdcl0, nomods_initdcl0): Use initdcl0_innards. + * parse.c: Regenerated. + +Tue Feb 17 11:54:16 1998 Jason Merrill + + * parse.y (simple_stmt): Use getdecls() to check for decl. + +Sat Feb 14 11:50:51 1998 Manfred Hollstein + + * Make-lang.in (DEMANGLER_INSTALL_NAME, DEMANGLER_CROSS_NAME): New + macros. + (c++.install-common): Install c++filt properly as native or as cross + variant. + (c++.uninstall): Add c++filt. + +Fri Feb 13 14:55:37 1998 Jason Merrill + + * call.c (standard_conversion): Fix multi-level ptr conversions. + +Fri Feb 13 14:06:22 1998 Mike Stump + + * init.c (build_new): Propagate error_mark_node up. + +Fri Feb 13 13:24:32 1998 Jason Merrill + + * parse.y (simple_stmt): If the condition isn't a declaration, + start the controlled block after the test. + +Fri Feb 13 02:26:10 1998 Andreas Schwab + + * call.c (build_over_call): Convert builtin abs, labs and fabs to + tree-codes. + * decl.c (init_decl_processing): Re-enable abs, labs and fabs as + builtins. + +Fri Feb 13 01:36:42 1998 Jason Merrill + + * call.c (standard_conversion): A BASE_CONV replaces an RVALUE_CONV. + +Fri Feb 13 00:21:59 1998 Jason Merrill + + * cp-tree.h: Add access_protected_virtual_node. + * class.c (init_class_processing): Initialize it. + * decl.c (xref_basetypes): Use it. + * parse.y (base_class_access_list): Likewise. + + * Make-lang.in (DEMANGLER_PROG): Add $(exeext). + (c++.install-common): Install c++filt. + +Thu Feb 12 12:46:51 1998 Benjamin Kosnik + + * decl.c (shadow_tag): Give error for typedef-ing built-in types. + +Wed Feb 11 23:28:05 1998 Mark Mitchell + + * call.c (reference_binding): Use comptypes when comparing + TYPE_MAIN_VARIANTS to handle non-canonical array/index types. + +Wed Feb 11 16:42:04 1998 Mark Mitchell + + * tree.c (is_overloaded_fn): Use really_overloaded_fn. + (really_overloaded_fn): Move check here from is_overloaded_fn. + (get_first_fn): Use really_overloaded_fn and is_overloaded_fn. + +Wed Feb 11 15:54:18 1998 Mark Mitchell + + * typeck.c (build_ptrmemfunc): Type-check pointer-to-member + conversions. + +Mon Feb 9 22:23:31 1998 Mark Mitchell + + * cp-tree.h (push_template_decl): Return the decl passed in, or an + equivalent duplicate. + * decl.c (pushtag): Use the return value from push_template_decl. + (duplicate_decls): When duplicating a template declaration, merge + the DECL_TEMPLATE_RESULTs as well. + (make_implicit_typename): Don't try to dive into typename types to + find a context for making a new implicit typename. + (start_decl): Use the return value from push_template_decl. + (grokdeclarator): Complain about declarations list `const operator + int'. Since we don't correctly handle in-class initializations of + non-static data members, complain about this (now illegal) + practice. Issue an error for initializations of non-const statics + since that is illegal as well, and since we don't handle that case + correctly either. + (start_function): Use the return value from push_template_decl. + (start_method): Likewise. + * decl2.c (grokfield): Likewise. Since the change to + grokdeclarator ensures that all initialized fields are in fact + static, remove a redundant test for TREE_PUBLIC. + * parse.y (initlist): Disable labeled initializers since they do + not work as per the documentation, and since they do not use the + same syntax as the C front end. + * pt.c (push_template_decl): Return the decl passed in, or an + equivalent duplicate. + (lookup_template_class): When searching in a nested context, + use the right arguments. + (uses_template_parms): Handle the DECL_INITIAL for a CONST_DECL. + * typeck.c (build_component_ref): Assign the correct type to the + result of build_vfn_ref. + +Tue Feb 10 23:56:46 1998 Jason Merrill + + * pt.c (convert_nontype_argument): Fix typo. + (check_explicit_specialization): Allow old-style specialization + of class template members. + +Tue Feb 10 20:36:52 1998 Jason Merrill + Manfred Hollstein + + * decl.c (grokdeclarator): Use DECL_USE_TEMPLATE instead + when deciding to override DECL_ASSEMBLER_NAME. + +Tue Feb 10 15:30:55 1998 Andrew MacLeod + + * decl2.c (lang_f_options): Add -fsquangle to option processing list. + * cp-tree.h (flag_do_squangling): Add declaration. + * lang-options.h: Add -fsquangle and -fno-squangle. + * method.c: Add macros and static variables for squangling. + (build_overload_name): Rename to build_mangled_name, add logic for B + compression, and split into process_modifiers and + process_overload_item. + (process_modifiers): New function, to handle constant, reference, + and pointer types. + (process_overload_item): New function, handles issue of type codes. + (build_overload_name): New function, start squangling and call + build_mangled_name. + (ALLOCATE_TYPEVEC, DEALLOCATE_TYPEVEC): Remove macro and expand inline. + (start_squangling): New function to initialize squangling structs. + (end_squangling): New function to destroy squangling structs. + (nrepeats): Rename variable to Nrepeats. + (issue_nrepeats): New function for issuing 'n' type repeats. + (check_ktype): New function to check for type K name compression. + (build_overload_nested_name): Add a check for K name compression. + (build_qualified_name): Add a check for K name compression and don't + use DECL_ASSEMBLER_NAME when squangling is on. + (check_btype): New function, checks for B type compression. + (build_static_name, build_decl_overload_real): Initiate squangling. + (build_typename_overload, build_overload_with_type): Initiate + squangling + +Sun Feb 8 23:47:38 1998 scott snyder + + * method.c (make_thunk): Avoid name buffer overflow. + +Sat Feb 7 16:48:54 1998 Jason Merrill + + * pt.c (instantiate_decl): Call cp_finish_decl for vars even if we + don't define them yet. + + * parse.y (nomods_initdcl0): Add constructor_declarator case. + +Fri Feb 6 21:32:25 1998 Richard Kenner + + * config-lang.in (diff_excludes): Use basename only. + +Thu Feb 5 19:10:40 1998 Jason Merrill + + * tinfo2.cc: Add tinfo for signed char. + +Thu Feb 5 14:38:23 1998 Mike Stump + + * search.c (compute_access): Handle protected constructors in derived + classes as accessible. + +Wed Feb 4 01:26:49 1998 Jason Merrill + + * expr.c (cplus_expand_expr, PCC_STATIC_STRUCT_RETURN code): + Call convert_from_reference sooner. + +Tue Feb 3 23:50:52 1998 Mark Mitchell + + * cvt.c (ocp_convert): Obtain the constant values from constant + decls even if the destination type is the same as the type of the + decl. + + * decl2.c (finish_file): Make sure that static inlines with + definitions are not marked DECL_EXTERNAL before returning. + +Tue Feb 3 22:43:42 1998 Jason Merrill + + * decl.c: Lose arg_looking_for_template. + (lookup_name_real): Likewise. + * parse.y: Lose processing_template_arg, template_arg1. + (primary): Likewise. + * spew.c (yylex): Set lastiddecl for PTYPENAMEs, too. + +Tue Feb 3 22:04:01 1998 Kriang Lerdsuwanakij + + * error.c (dump_decl): Fix type of default arguments for template + template parameters and nontype template parameters. + * parse.y (template_parm): Handle invalid default template + template arguments here. + + * parse.y (template_parm): Use template_arg instead of PTYPENAME + for default template template argument. + * pt.c (coerce_template_parms): Merge default template argument + codes. Can treat RECORD_TYPE as template name if it is implicitly + created. Fix argument index in error message. + * typeck.c (comptypes): Merge template argument comparison codes in + TEMPLATE_TEMPLATE_PARM and RECORD_TYPE. + +Tue Jan 6 01:42:44 1998 Mumit Khan + + * lex.c (file_name_nondirectory): Also check for '/'. + +Mon Feb 2 11:24:22 1998 Mark Mitchell + + * parse.y (primary): Deal with statement-expressions in + templates. + * pt.c (tsubst_copy): Handle BIND_EXPR. + * tree.c (mapcar): Likewise. + + * call.c (add_template_candidate_real): Pass extra parameter to + fn_type_unification. + * cp-tree.h (fn_type_unification): Add parameter. + * pt.c (fn_type_unification): Add additional parameter to deal with + static member functions. + (get_bindings): Deal with static member functions. + + * cp-tree.h (DECL_NONSTATIC_MEMBER_FUNCTION_P): New macro. + (revert_static_member_fn): Declare. + * decl.c (revert_static_member_fn): Remove declaration. Change + linkage from internal to external. + (cp_finish_decl): Deal with virtual functions in classes local to + template functions. + * decl2.c (finish_file): Don't forget to emit increment/decrement + expressions in initializers for file-scope variables. + * parse.y (typename_sub2): If the typename doesn't names a + template, rather than a type, issue an error message. + * pt.c (check_explicit_specialization): Handle specializations of + static member functions. + (coerce_template_parms): Handle offset references to lists of + member functions. + * search.c (note_debug_info_needed): Don't crash when handed a + type which is being defined. + * typeck.c (complete_type): Don't crash when handed NULL_TREE; + that can happen with some illegal code. + +Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi + + * call.c (user_harshness): Initialize `code' to 0. + (build_method_call): Initialize `candidates', `cp' and `len' to 0. + (null_ptr_cst_p): Add parentheses around && within ||. + (standard_conversion): Likewise. + (z_candidate): Likewise. + (build_user_type_conversion_1): Initialize `args' to NULL_TREE. + (build_object_call): Likewise for `mem_args'. + (build_new_op): Likewise for `mem_arglist'. Add `return' from + default case in enumeration switch. + + * class.c (build_vtable_entry): Add explicit braces to avoid + ambiguous `else'. + (build_class_init_list): Likewise. + (finish_struct_1): Initialize `width' to 0. + (instantiate_type): Initialize `name' to NULL_TREE. Add + explicit braces to avoid ambiguous `else'. + + * cvt.c (convert_to_aggr): Add explicit braces to avoid ambiguous + `else'. + + * decl.c (grok_reference_init): Eliminate unused parameter, all + callers changed. + (record_builtin_type): Initialize `tdecl' to NULL_TREE. + (init_decl_processing): Initialize `vb_off_identifier' to NULL_TREE. + (cp_finish_decl): Initialize `ttype' to NULL_TREE. + (grokdeclarator): Add parentheses around && within ||. Add + explicit braces to avoid ambiguous `else'. + (grokparms): Initialize `type' to NULL_TREE. + (xref_tag): Remove unused label `just_return'. + (finish_enum): Initialize `minnode' and `maxnode' to NULL_TREE. + (finish_function): Initialize `cond' and `thenclause' to NULL_TREE. + (hack_incomplete_structures): Add parentheses around assignment + used as truth value. + + * decl2.c (coerce_delete_type): Hide definition of `e3'. + + * error.c: Include . + (dump_expr): Change the type of `i' to size_t. Remove unused + label `error'. + + * except.c (init_exception_processing): Remove unused variable `d'. + (expand_throw): Likewise for `label'. + + * friend.c (add_friends): Add explicit braces to avoid ambiguous + `else'. + + * init.c (sort_member_init): Initialize `last_field' to NULL_TREE. + (sort_base_init): Likewise for `binfo'. + (expand_member_init): Likewise for `rval'. + (build_member_call): Add parentheses around assignment used as + truth value. + (build_offset_ref): Add explicit braces to avoid ambiguous `else'. + (build_new): Initialize `nelts' to NULL_TREE. Initialize + `old_immediate_size_expand' to 0. + (build_new_1): Initialize `nelts' and `alloc_node' to NULL_TREE. + (build_vec_delete_1): Remove unused variable `block'. + (expand_vec_init): Initialize `itype' to NULL_TREE. + + * lex.c: Include if we don't have . Protect + declaration of `index' and `rindex' with autoconf macros. + (reinit_parse_for_expr): Remove unused variables + `look_for_semicolon' and `look_for_lbrac'. + (cons_up_default_function): Initialize `args' to NULL_TREE. + (readescape): Initialize `firstdig' to 0. + (real_yylex): Add parentheses around assignment used as truth value. + + * method.c: Include if we don't have . + Protect declaration of `index' with autoconf macro. + + * parse.y (primary): Add explicit braces to avoid ambiguous `else'. + Initialize `type' to NULL_TREE. + (structsp): Remove unused variable `id'. + + * pt.c (coerce_template_parms): Add explicit braces to avoid + ambiguous `else'. + (lookup_template_class): Initialize `template' to NULL_TREE. + (instantiate_class_template): Remove unused variable `name' and `e'. + (tsubst): Likewise for `i'. Initialize `last' to NULL_TREE. + (do_poplevel): Initialize `saved_warn_unused' to 0. + (type_unification): Remove unused varable `parm'. + (unify): Likewise for `j'. + + * repo.c (init_repo): Add parentheses around assignment used as + truth value. + (finish_repo): Remove unused varable `p'. + + * search.c (get_binfo): Initialize `type' to NULL_TREE. + (get_base_distance): Likewise. + (lookup_field): Initialize `rval_binfo_h', `type', `basetype_path' + and `new_v' to NULL_TREE. + (lookup_fnfields): Likewise for `rval_binfo_h'. + (breadth_first_search): Add parentheses around assignment used as + truth value. + (get_template_base): Initialize `type' to NULL_TREE. + + * sig.c (append_signature_fields): Initialize `last_mfptr' to + NULL_TREE. + (build_signature_table_constructor): Likewise for + `last_rhs_field', `pfn' and `vt_off'. + (build_sigtable): Likewise for `init'. + + * tree.c (break_out_calls): Initialize `t2' to NULL_TREE. + (propagate_binfo_offsets): Likewise for `delta'. + (hash_tree_cons): Initialize hashcode to 0. + (can_free): Likewise for `size'. + (cp_tree_equal): Add explicit braces to avoid ambiguous `else'. + + * typeck.c (convert_sequence): Hide prototype. + (common_type): Add explicit braces to avoid ambiguous `else'. + (comp_target_types): Likewise. + (build_x_function_call): Initialize `ctypeptr' to NULL_TREE. + (build_function_call_real): Add explicit braces to avoid ambiguous + `else'. + (convert_arguments): Initialize `called_thing' to 0. + (convert_for_initialization): Initialize `savew' and `savee' to 0. + + * typeck2.c (incomplete_type_error): Initialize `errmsg' to 0. + (digest_init): Initialize `old_tail_contents' to NULL_TREE. + (build_x_arrow): Likewise for `last_rval'. + + * xref.c (GNU_xref_decl): Initialize `cls' to 0. + +Sun Feb 1 12:45:34 1998 J"orn Rennecke + + * decl.c (init_decl_processing): Use set_sizetype. + * decl2.c (sizetype): Don't declare. + * typeck.c (c_sizeof): Convert result of *_DIV_EXPR to sizetype. + (c_sizeof_nowarn, build_binary_op_nodefault): Likewise. + (build_component_addr, unary_complex_lvalue): Likewise. + * rtti.c (expand_class_desc): Likewise. + * class.c (get_vfield_offset): Likewise. + +Thu Jan 29 10:39:30 1998 Mark Mitchell + + * pt.c (convert_nontype_argument): Move check for is_overloaded_fn + early to avoid bogus error. Handle overloaded function + names provided as template arguments correctly. + (coerce_template_parms): Don't mishandle overloaded functions when + dealing with template template parameters. + (lookup_template_class): Issue an error message, rather than + crashing, when the TYPE_DECL provided is not a template type. + +Wed Jan 28 23:14:44 1998 Jason Merrill + + * class.c (instantiate_type): Don't just return a known type if + it's wrong. + +Wed Jan 28 11:04:07 1998 Mark Mitchell + + * class.c (instantiate_type): Remove handling of FUNCTION_DECL + since that code could never be reached. + + * error.c (dump_decl): Avoid aborting in the midst of printing an + error message about an illegal template declaration. + + * parse.y (structsp): Print an error message, rather than crashing, + when a class-head does not name a class. + + * pt.c (convert_nontype_argument): Allow REAL_TYPE and COMPLEX_TYPE + template arguments as a g++ extension. + + * cp-tree.def (ALIGNOF_EXPR): New tree code. + * decl2.c (grok_alignof): If processing_template_decl, just store + the expression. + * typeck.c (c_alignof): Likewise. + * decl2.c (build_expr_from_tree): Handle ALIGNOF_EXPR. + * error.c (dump_expr): Likewise. + * pt.c (tsubst_copy): Likewise. + * tree.c (cp_tree_equal): Likewise. + * pt.c (uses_template_parms): Correctly determine whether or not a + SIZEOF_EXPR/ALIGNOF_EXPR uses template parameters so that constant + folding can be done. + + * cp-tree.h (grok_enum_decls): Remove type parameter. + * decl.c (grok_enum_decls): Likewise. + * decl2.c (grok_x_components): Call grok_enum_decls + unconditionally, since it will do nothing if there is no + current_local_enum. Use the new calling sequence. + * pt.c (tsubst_enum): Use the new calling sequence for + grok_enum_decls. + + * decl.c (start_function): Make member functions of local classes + in extern inline functions have comdat linkage here... + (grokdeclarator): Rather than here. + +Wed Jan 28 10:55:47 1998 Jason Merrill + + * pt.c (convert_nontype_argument): Use decl_constant_value. + +Tue Jan 27 16:42:21 1998 Mark Mitchell + + * call.c (add_template_candidate_real): New function. + (add_template_candidate): Use it. + (add_template_conv_candidate): Likewise. + (joust): Pass extra argument to more_specialized. + * class.c (instantiate_type): Handle a single FUNCTION_DECL. + (is_local_class): Remove. + (finish_struct): Check TI_PENDING_SPECIALIZATION_FLAG. + * cp-tree.h (is_local_class): Remove. + (perform_array_to_pointer_conversion): Likewise. + (finish_member_template_decl): Add. + (check_explicit_specialization): Return a tree, not an int. + (more_specialized): Take additional argument. + (get_bindings): Likewise. + (TI_PENDING_SPECIALIZATION_FLAG): New macro. + * cvt.c (perform_qualification_conversions): Use comp_ptr_ttypes. + (perform_array_to_pointer_conversion): Remove. + * decl.c (saved_scope): Add processing_specialization, + processing_explicit_instantiation fields. + (maybe_push_to_top_level): Save them. + (pop_from_top_level): Restore them. + (grokfndecl): Use new return value from + check_explicit_specialization. + (start_decl): Don't check flag_guiding_decls before pushing + decls. + (cp_finish_decl): Remove previous (bogus) change. + (grok_declarator): Use decl_function_context rather than + is_local_class. + * decl2.c (finish_file): Pass extra argument to get_bindings. + (build_expr_from_tree): Let build_x_component_ref check + validity of arguments rather than doing it here. + * lex.c (cons_up_default_function): Remove code fooling with + processing_specialization, processing_explicit_instantiation + flags, as that is now done in {maybe_push_top,pop_from}_top_level. + * method.c (build_overload_identifier): Mangle local classes in + template functions correctly. + * parse.y (finish_member_template_decl): Move to pt.c. + * pt.c (finish_member_template_decl): Moved here from parse.y. + (print_candidates): New function. + (determine_specialization): Change interface. Properly look for + most specialized versions of template candidates. + (check_explicit_specialization): Fully process explicit + instantiations. + (push_template_decl): Avoid looking at CLASSTYPE fields in + FUNCTION_DECLS. + (determine_overloaded_function): Remove. + (convert_nontype_argument): Change name from + convert_nontype_parameter. Use determine_overloaded_function + instead of instantiate_type. + (mangle_class_name_for_template): Handle type contexts as well as + function contexts. + (classtype_mangled_name): Likewise. + (lookup_template_class): Likewise. + (tsubst): Likewise. + (more_specialized): Take explict template arguments as a + parameter. + (most_specialized): Likewise. + (get_bindings): Likewise. Check that return types match before + proclaiming a function a match. + (do_decl_instantiation): Remove code searching for function to + instantiate; that is now done in check_explicit_specialization. + (add_maybe_template): Pass extra argument to get_bindings. + * tree.c (really_overloaded_fn): Use is_overloaded_fn to simplify + implementation. + * typeck.c (build_component_ref): Check for invalid arguments. + +Tue Jan 27 01:44:02 1998 Jason Merrill + + * expr.c (cplus_expand_expr, AGGR_INIT_EXPR): Don't check that + return_target and call_target are equivalent. + + * pt.c (type_unification_real): Just accept function parms that + don't use any template parms. + +Sun Jan 25 03:30:00 1998 Jason Merrill + + * decl.c (cp_finish_decl): When bailing on a comdat variable, also + unset DECL_NOT_REALLY_EXTERN. + + * parse.y (typename_sub*): Fix std::. + +Sat Jan 24 12:13:54 1998 Jason Merrill + + * error.c (dump_decl): Fix type default template args. + (dump_type): Hand TEMPLATE_DECL off to dump_decl. + +Fri Jan 23 18:34:37 1998 Mumit Khan + + * lex.c (DIR_SEPARATOR): Define to be '/' if not already defined. + (file_name_nondirectory): Use. + +Wed Jan 21 10:29:57 1998 Kriang Lerdsuwanakij + + * pt.c (coerce_template_parms): Don't access elements of ARGLIST + that are not really present. Substitute default arguments in + template template arguments. Correctly convert TEMPLATE_DECL to + TEMPLATE_TEMPLATE_PARM. + (comp_template_args): TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM + are no longer treated specially here. + * parse.y (template_template_parm): Fix copy error. + * decl.c (grokdeclarator): Warn about missing `typename' for nested + type created from template template parameters. + * parse.y (bad_parm): Likewise + + * class.c (finish_struct): Handle TEMPLATE_TEMPLATE_PARM. + (push_nested_class): Likewise. + * cp-tree.def (TEMPLATE_TEMPLATE_PARM): New tree code. + * cp-tree.h (DECL_TEMPLATE_TEMPLATE_PARM_P): New macro. + (copy_template_template_parm): Declare. + * decl.c (arg_looking_for_template): New variable. + (lookup_name_real): Handle TEMPLATE_TEMPLATE_PARM. + Try to return TEMPLATE_DECL or TEMPLATE_TEMPLATE_PARM + node if arg_looking_for_template is nonzero. + (pushdecl): Handle TEMPLATE_TEMPLATE_PARM. + (grok_op_properties, xref_tag, xref_basetypes): Likewise. + (grokdeclarator): Handle TEMPLATE_DECL. + * decl2.c (constructor_name_full): Handle TEMPLATE_TEMPLATE_PARM. + * error.c (dump_type): Add TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM. + (dump_type_prefix, dump_type_suffix): Handle TEMPLATE_TEMPLATE_PARM. + (dump_decl): Handle unnamed template type parameters. + Handle template template parameters. + (dump_function_name): Handle template template parameters. + * init.c (is_aggr_typedef, is_aggr_type, get_aggr_from_typedef): + Handle TEMPLATE_TEMPLATE_PARM. + * method.c (build_template_template_parm_names): New function. + (build_template_parm_names): Handle TEMPLATE_DECL. + (build_overload_nested_name, build_overload_name): + Handle TEMPLATE_TEMPLATE_PARM. + * parse.y (maybe_identifier): New nonterminal. + (template_type_parm): Use it. + (template_template_parm, template_arg1): New nonterminal. + (template_parm): Add template_template_parm rules. + (template_arg): Set processing_template_arg. + (template_arg1): Rules moved from template_arg. + (primary, nonnested_type): Set arg_looking_for_template if we are + processing template arguments. + * pt.c (begin_member_template_processing): Handle TEMPLATE_DECL. + (process_template_parm): Handle template template parameters. + (coerce_template_parms, comp_template_args): Likewise. + (mangle_class_name_for_template, lookup_template_class): Likewise. + (uses_template_parms): Handle TEMPLATE_DECL and + TEMPLATE_TEMPLATE_PARM. + (current_template_args): Handle TEMPLATE_DECL. + (tsubst, tsubst_copy, unify): Handle TEMPLATE_TEMPLATE_PARM. + * search.c (dfs_walk, dfs_record_inheritance): + Handle TEMPLATE_TEMPLATE_PARM. + * tree.c (copy_template_template_parm): New function. + (mapcar): Handle TEMPLATE_TEMPLATE_PARM. + * typeck.c (comptypes): Handle TEMPLATE_TEMPLATE_PARM. + +Mon Jan 19 22:40:03 1998 Mark Mitchell + + * decl.c (start_decl): Don't allow duplicate definitions of static + data members. + + * call.c (build_user_type_conversion_1): Handle user-defined + template conversion operators correctly. + + * decl2.c (build_expr_from_tree): Issue an error message if the + object in a COMPONENT_REF is a TEMPLATE_DECL. + + * typeck.c (incomplete_type_error): Handle TEMPLATE_TYPE_PARMs. + + * class.c (is_local_class): New function. + * cp-tree.h (is_local_class): Declare it. + (last_tree): Likewise. + (begin_tree): Likewise. + (end_tree): Likewise. + (lookup_template_class): Change prototype. + * decl.c (cp_finish_decl): Check for NULL where necessary. + Consider FUNCTION_DECLS to declare objects with top-level binding, + when calling make_decl_rtl. + (grokdeclarator): Give members of local classes internal linkage. + (start_function): Remove declaration of last_tree. + (finish_function): Set flag_keep_inline_functions around call to + rest_of_compilation if we are processing a member function in a + local class. + (start_method): Call push_template_decl for member functions of + local classes in template functions. + * decl2.c (import_export_decl): Don't give external linkage to + instantiations of templates with internal linkage. + * parse.y (last_tree): Remove declaration. + (template_type): Pass extra parameter to lookup_template_class. + (self_template_type): Likewise. + (structsp): Move call to reset_specialization into left_curly. + (left_curly): Call reset_specialization, and begin_tree. + * pt.c (saved_trees): New variable. + (mangle_class_name_for_template): Change prototype. Use + additional function context to name local classes in templates + correctly. + (classtype_mangled_name): Pass the context. + (push_template_decl): Handle local classes and templates, and + member functions for such classes. + (convert_nontype_parameter): Fix handling of pointer-to-member + constants. + (lookup_template_class): Handle local classes in templates. + (tsubst): Likewise. Don't assume that template instantiations + have external linkage; pay attention to the template declaration. + (mark_decl_instantiated): Likewise. + (begin_tree): New function. + (end_tree): Likewise. + + * decl.c (xref_basetypes): Don't call complete_type for basetypes + that involve template parameters; that can lead to infinite + recursion unnecessarily. + + * pt.c (register_specialization): Do not register specializations + that aren't ready to be registered yet. + (check_explicit_specialization): Handle explicit specialization of + constructors and destructors. + (build_template_decl): New function. + (push_template_delc): Handle out-of-class specializations of + member templates. + + * pt.c (check_explicit_specialization): Set up the template + information before registering the specialization. + (coerce_template_parms): Fix thinko. + (tsubst): Handle specializations of member templates correctly. + + * class.c (finish_struct_methods): Remove calls to + check_explicit_specialization from here. + (finish_struct): And insert them here. + * cp-tree.h (perform_qualification_conversions): New function. + (perform_array_to_pointer_conversion): Likewise. + (begin_explicit_instantiation): Likewise. + (end_explicit_instantiation): Likewise. + (determine_specialization): Renamed from + determine_explicit_specialization. + (comp_template_parms): New function. + (processing_explicit_instantiation): New variable. + * cvt.c (perform_qualification_conversions): New function. + (perform_array_to_pointer_conversion): Likewise. + * decl.c (duplicate_decls): Don't consider template functions + alike unless they have the same parameters. Refine handling of + instantiation/specialization mismatches. + (start_decl): Don't call pushdecl for template specializations, + since they don't affect overloading. + (start_function): Likewise. + (grokfndecl): Call check_explicit_specialization a little later. + Don't call duplicate_decls for memberm template specializations. + (grokdeclarator): Don't update template_count for classes that are + themselves specializations. Remove use of `2' as parameter to + grokfndecl since that value isn't used. + * lex.c (cons_up_default_function): Save and restore + processing_explicit_instantiation around calls to grokfield. + * parse.y (finish_member_template_decl): New function. + (component_decl_1): Use it. + (fn.def2): Likewise. + (template_arg_list_opt): New nonterminal. + (template_type): Use it. + (self_template_type): Likewise. + (template_id): Likewise. + (object_template_id): Likewise. + (notype_template_declarator): Likwise. + (begin_explicit_instantiation): Likewise. + (end_explicit_instantiation): Likewise. + (explicit_instantiation): Use them. + * pt.c (coerce_template_parms): Add parameters. + (processing_explicit_instantiation): New variable. + (convert_nontype_parameter): New function. + (determine_overloaded_function): Likewise. + (begin_explicit_instantiation): Likewise. + (end_explicit_instantiation): Likewise. + (retrieve_specialization): Likewise. + (register_specialization): Likewise. + (processing_explicit_specialization): Removed. + (determine_specialization): Handle specializations of member + functions of template class instantiations. + (check_explicit_specialization): Refine to conform to standard. + (comp_template_parms): New function. + (coerce_template_parms): Call convert_nontype_parameter. + (tsubst): Refine handling of member templates. Use + register_specialization. + (instantiate_template): Use retrieve_specialization. + (do_decl_instantiation): Likewise. + (instantiate_decl): Likewise. + (type_unification): Improve handling of explict template + arguments. + * tree.c (mapcar): Return error_mark_node, rather than aborting, + on VAR_DECLS, FUNCTION_DECLS, and CONST_DECLS. + * typeck.c (build_unary_op): Call determine_specialization, rather + than determine_explicit_specialization. + +Mon Jan 19 13:18:51 1998 Jason Merrill + + * cvt.c (build_up_reference): A TARGET_EXPR has side effects. + +Fri Jan 16 11:40:50 1998 Bruno Haible + + * error.c (dump_decl): For enum tags, output the tag, not its value. + +1998-01-13 Brendan Kehoe + + * decl.c (init_decl_processing): Only call init_rtti_processing + FLAG_RTTI is set. + +Mon Jan 12 01:35:18 1998 Jason Merrill + + * init.c (build_new_1): Split out from build_new. + (build_new): Just return a NEW_EXPR. + * expr.c (cplus_expand_expr): Handle NEW_EXPR. + + * decl2.c (get_temp_regvar): Tweak. + + * cp-tree.h (TREE_CALLS_NEW): Comment out. + * class.c (resolves_to_fixed_type_p): Remove use. + * method.c (build_opfncall): Likewise. + * call.c (build_new_op): Likewise. + +Wed Jan 7 23:47:13 1998 Jason Merrill + + * exception.cc (__eh_alloc, __eh_free): New fns. + (__cp_push_exception, __cp_pop_exception): Use them. + (__uncatch_exception): Call terminate here if no exception. + * except.c (build_terminate_handler): New fn. + (expand_start_catch_block): Use it. + (expand_exception_blocks): Likewise. + (alloc_eh_object): New fn. + (expand_throw): Use it. Protect exception init with terminate. + * typeck.c (build_modify_expr): Remove code that ignores trivial + methods. + +Mon Dec 22 11:36:27 1997 Kaveh R. Ghazi + + * call.c (add_builtin_candidate): Add default case in enumeration + switch. + (build_new_op): Likewise. + (convert_like): Likewise. + * cvt.c (build_expr_type_conversion): Likewise. + * tree.c (real_lvalue_p): Likewise. + (lvalue_p): Likewise. + (cp_tree_equal): Likewise. + * typeck.c (comptypes): Likewise. + (build_component_ref): Likewise. + (build_function_call_real): Likewise. + (build_binary_op_nodefault): Likewise. + (build_unary_op): Likewise. + (build_modify_expr): Likewise. + * typeck2.c (initializer_constant_valid_p): Likewise. + +Sun Dec 21 15:59:00 1997 Nick Clifton + + * decl2.c (lang_decode_option): Add support for -Wunknown-pragmas. + +Thu Dec 18 14:51:50 1997 Mark Mitchell + + * pt.c (coerce_template_parms): Make sure to digest_init if + possible. + + * decl.c (duplicate_decls): Make the newdecl virtual if the + olddecl was, just as is done with other attributes of olddecl. + +Thu Dec 18 14:43:19 1997 Jason Merrill + + * typeck.c (unary_complex_lvalue): Ignore op0 when taking the + address of an OFFSET_REF. + + * cp-tree.def: Add AGGR_INIT_EXPR. + * error.c, tree.c, typeck.c: Replace uses of NEW_EXPR with + AGGR_INIT_EXPR where appropriate. + * expr.c (cplus_expand_expr): Likewise. Simplify. + + * decl2.c (finish_file): Remove call to register_exception_table. + +Wed Dec 17 17:08:52 1997 Benjamin Kosnik + + * pt.c (instantiate_class_template): Don't do injection when + processing_template_decl is true, as pollutes current_binding_level + for base classes. + +Wed Dec 17 21:17:39 1997 Peter Schmid + + * pt.c (maybe_fold_nontype_arg): Add prototype. + +Tue Dec 16 10:31:20 1997 Jason Merrill + + * tree.c (mapcar): Handle TRY_CATCH_EXPR et al. + * error.c (dump_expr): Likewise. + +Mon Dec 15 12:22:04 1997 Jason Merrill + + * typeck.c (build_function_call_real): Remove "inline called before + definition" pedwarn. + + * pt.c (coerce_template_parms): Use maybe_fold_nontype_arg. + +Sun Dec 14 22:34:20 1997 Jason Merrill + + * cvt.c (cp_convert_to_pointer): Fix base conversion of pm's. + + * pt.c (type_unification_real): Change __null to type void* with + a warning. + +Sun Dec 14 20:38:35 1997 Mark Mitchell + + * call.c (implicit_conversion): Don't call + build_user_type_conversion_1 with a NULL expr, since it will + crash. + + * pt.c (unify): Don't try to unify array bounds if either array is + unbounded. + +Fri Dec 12 16:09:14 1997 Jason Merrill + + * errfn.c (cp_pedwarn, cp_pedwarn_at, cp_error_at, cp_warning_at): + Replace extern decls with casts. + + * decl.c (expand_start_early_try_stmts): Don't mess with a sequence. + Update last_parm_cleanup_insn. + (store_after_parms): Remove. + * cp-tree.h: Adjust. + +Thu Dec 11 22:18:37 1997 Jason Merrill + + * decl2.c (comdat_linkage): Also set DECL_COMDAT. + (finish_file): Check DECL_COMDAT instead of weak|one_only. + (import_export_vtable): Use make_decl_one_only instead of + comdat_linkage for win32 tweak. + (import_export_decl): Likewise. + * pt.c (mark_decl_instantiated): Likewise. + + * decl2.c (finish_file): Lose handling of templates in pending_statics. + +Thu Dec 11 21:12:09 1997 Jason Merrill + + * decl2.c (finish_file): Lose call to expand_builtin_throw. + * except.c (expand_builtin_throw): Remove. + * cp-tree.h: Remove ptr_ptr_type_node. + * decl.c: Likewise. + +Thu Dec 11 20:43:33 1997 Teemu Torma + + * decl.c (ptr_ptr_type_node): Define. + (init_decl_processing): Initialize it. + * cp-tree.h: Declare it. + * exception.cc (__cp_exception_info): Use __get_eh_info. + (__cp_push_exception): Likewise. + (__cp_pop_exception): Likewise. + + From Scott Snyder : + * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of + saved_pc. + (init_exception_processing): Removed saved_pc initialization. + +Wed Dec 10 11:04:45 1997 Jason Merrill + + * pt.c (instantiate_decl): Defer all templates but inline functions. + +Mon Dec 8 23:17:13 1997 Jason Merrill + + * init.c (expand_vec_init): Don't fold a list of parameters. + + * decl.c (copy_args_p): Handle copy elision for types with virtual + bases. + * call.c (build_over_call): Likewise. + +Sun Dec 7 22:38:12 1997 Mark Mitchell + + * pt.c (lookup_template_function): Copy the template arguments, + not just the list containing them, to the permanent obstack. + +Sun Dec 7 15:53:06 1997 Jason Merrill + + * except.c (expand_start_catch_block): suspend_momentary for the + terminate handler. + + * error.c (dump_decl): Handle LOOKUP_EXPR. + +Sun Dec 7 15:45:07 1997 Mark Mitchell + + * rtti.c (build_dynamic_cast): Copy the cast-to type to the + permanent obstack if we are processing a template decl. + * typeck.c (build_static_cast): Likewise. + (build_const_cast): Likewise. + (build_reinterpret_cast): Likewise. + + * pt.c (coerce_template_parms): Coerce some expressions, even + when processing_template_decl. + +Sun Dec 7 01:46:33 1997 Bruno Haible + + * typeck.c (build_binary_op_nodefault, pointer_diff): Symmetric + handling of pointer difference expressions. + + * typeck.c (comp_target_types): Comparison of function/method types + is independent of nptrs. + +Sun Dec 7 01:40:27 1997 Mark Mitchell + + * pt.c (tsubst): Avoid creating pointer to reference and + reference to reference types. + +Sat Dec 6 01:29:37 1997 Jason Merrill + + * parse.y (do_id): New nonterminal. + (template_id): Use it. + +Fri Dec 5 01:17:34 1997 Jason Merrill + + * parse.y (template_id): do_identifier for PFUNCNAMEs, too. + * spew.c (yylex): Don't do_identifier here. + * decl2.c (build_expr_from_tree): Revert last change. + + * decl2.c (build_expr_from_tree): Expand the name for a method call. + * parse.y (object_template_id): Don't try to take the DECL_NAME. + +Wed Dec 3 20:02:39 1997 Jason Merrill + + * init.c (build_new): Use a TARGET_EXPR instead of SAVE_EXPR for + alloc_expr. + * call.c (build_op_delete_call): Adjust. + + * except.c (expand_end_catch_block): Lose rethrow region. + (expand_start_catch_block): Likewise. + (expand_end_catch_block): Don't expand_leftover_cleanups. + +Wed Dec 3 13:24:04 1997 Benjamin Kosnik + + * pt.c (tsubst): Remove tree_cons call (places redundant info into + DECL_TEMPLATE_INSTANTIATION). + +Wed Dec 3 11:44:52 1997 Jason Merrill + + * tree.c (is_overloaded_fn): Handle getting a fn template. + (really_overloaded_fn): Likewise. + * error.c (dump_decl): Handle TEMPLATE_ID_EXPRs better. + * pt.c (check_explicit_specialization): Tweak. + (determine_explicit_specialization): Tweak. + + * tree.c, cp-tree.h (get_target_expr): New fn. + +Wed Dec 3 08:47:27 1997 Paul Eggert + + * pt.c (check_explicit_specialization): Fix misspelling in + diagnostic: `preceeded'. + * typeck.c (get_delta_difference): Fix misspelling in diagnostic: + `conversiona'. + +1997-12-02 Mark Mitchell + + * pt.c (determine_explicit_specialization): Avoid an internal + error for bad specializations. + + * method.c (build_overload_value): Handle SCOPE_REF. + +Tue Dec 2 19:18:50 1997 Mike Stump + + * class.c (prepare_fresh_vtable): Enable even more complex MI + vtable names. + +Tue Dec 2 01:37:19 1997 Jason Merrill + + * exception.cc (__check_eh_spec): Optimize a bit. + + * exception.cc (__cp_pop_exception): Lose handler arg. + * except.c (do_pop_exception): Likewise. + (push_eh_cleanup): Let the cleanup mechanism supply the handler. + (expand_end_catch_block): Likewise. + +Fri Nov 28 01:58:14 1997 Jason Merrill + + * pt.c (check_explicit_specialization): Complain about using a + template-id for a non-specialization. + +Fri Nov 28 12:35:19 1997 Scott Christley + + * repo.c: Prototype rindex only if needed. + * xref.c: Likewise. + +Fri Nov 28 01:56:35 1997 Bruno Haible + + * error.c (dump_decl): Handle TEMPLATE_ID_EXPR. + +Thu Nov 27 00:59:46 1997 Jason Merrill + + * typeck.c (build_const_cast): Handle references here instead of + handing off to convert_to_reference. + + * except.c: Lose Unexpected, SetTerminate, SetUnexpected, + TerminateFunctionCall. + (init_exception_processing): Likewise. Terminate et al are now + the fns, not ADDR_EXPRs. + (various): Lose redundant assemble_external calls. + (do_unwind): s/BuiltinReturnAddress/builtin_return_address_fndecl/. + + * cp-tree.h (struct lang_decl_flags): Add comdat. + (DECL_COMDAT): New macro. + * decl.c (duplicate_decls): Propagate it. + (cp_finish_decl): Handle it. + * decl2.c (import_export_decl): Just set DECL_COMDAT on VAR_DECLs. + + * class.c: Remove static pending_hard_virtuals. + (add_virtual_function): Take pointers to pending_virtuals + and pending_hard_virtuals. + (finish_struct_1): Pass them. Declare pending_hard_virtuals. + +Wed Nov 26 20:28:49 1997 Jason Merrill + + * decl2.c (import_export_vtable): If we support one_only but not + weak symbols, mark instantiated template vtables one_only. + (import_export_decl): Likewise for tinfo functions. + (finish_vtable_vardecl): Also write out vtables from explicitly + instantiated template classes. + * pt.c (mark_class_instantiated): Revert last change. + + * except.c (expand_throw): Call mark_used on the destructor. + +Wed Nov 26 15:13:48 1997 Jeffrey A Law (law@cygnus.com) + + * lex.c (lang_init): Enable flag_exceptions by default if no + command line switch was specified. + +1997-11-26 Mark Mitchell + + * pt.c (unify): Handle `void' template parameters in + specializations. + +Wed Nov 26 01:11:24 1997 Jason Merrill + + * rtti.c (build_dynamic_cast): Handle template case here. + (build_dynamic_cast_1): Not here. + + * typeck2.c (digest_init): Make copies where appropriate. + + * decl2.c (delete_sanity): resolve_offset_ref. + + * except.c: Call terminate without caching so many bits. + + * except.c (expand_start_catch_block): Fix catching a reference + to pointer. + +Tue Nov 25 11:28:21 1997 Jason Merrill + + * init.c (build_new): Copy size to the saveable obstack. + + * init.c (build_new): Stick a CLEANUP_POINT_EXPR inside the + TRY_CATCH_EXPR for now. + +Mon Nov 24 12:15:55 1997 Jason Merrill + + * typeck.c (mark_addressable): Don't assume a FUNCTION_DECL + has DECL_LANG_SPECIFIC. + + * exception.cc (struct cp_eh_info): Add handlers field. + (__cp_push_exception): Initialize it. + (__cp_pop_exception): Decrement it. Don't pop unless it's 0. + (__throw_bad_exception): Remove. + * except.c (call_eh_info): Add handlers field. + (get_eh_handlers): New fn. + (push_eh_cleanup): Increment handlers. + +Fri Nov 21 12:22:07 1997 Jason Merrill + + * except.c (expand_start_eh_spec): Use the try/catch code. + (expand_end_eh_spec): Likewise. Call __check_eh_spec instead of + doing everything inline. + (init_exception_processing): throw_type_match now takes + const void pointers. + * exception.cc (__check_eh_spec): New fn. + * inc/exception: Neither terminate nor unexpected return. + * decl.c: Make const_ptr_type_node public. + * tinfo2.cc (__throw_type_match_rtti): Take the typeinfos constly. + + * except.c (expand_start_catch_block): We only need the rethrow + region for non-sjlj exceptions. + (expand_end_catch_block): Likewise. Use outer_context_label_stack. + +Thu Nov 20 14:40:17 1997 Jason Merrill + + * Make-lang.in (CXX_LIB2FUNCS): Add new op new and op delete objs. + (various.o): Likewise. + * inc/new: Add placement deletes. Add throw specs for default new. + * new.cc (set_new_handler): Move here from libgcc2. + * new1.cc (new (nothrow)): Catch a bad_alloc thrown from the handler. + (new): Move from libgcc2. Throw bad_alloc. + * new2.cc: Move the rest of the op news and op deletes from libgcc2. + * decl.c (init_decl_processing): Update exception specs on new and + delete. + + * method.c (build_decl_overload_real): Don't mess with global + placement delete. + + * init.c (build_new): Check for null throw spec, not nothrow_t. + + * decl.c (duplicate_decls): Don't complain about different exceptions + from an internal declaration. + + * call.c (build_op_delete_call): Fix check for member fns again. + + * decl2.c (import_export_decl): Interface hackery affects + virtual synthesized methods. + +Wed Nov 19 18:24:14 1997 Jason Merrill + + * decl.c (start_decl): Don't just complain about a mismatched + scope, fix it. + + * decl.c (make_implicit_typename): Handle case where t is not + actually from context. + * tree.c (get_type_decl): Lose identifier case. + * spew.c (yylex): Lose useless call to identifier_typedecl_value. + * parse.y (nonnested_type): Just use lookup_name. + (complex_type_name): Just use IDENTIFIER_GLOBAL_VALUE. + +Wed Nov 19 11:45:07 1997 Michael Tiemann + + * error.c (dump_function_name): Test DECL_LANG_SPECIFIC in case + T was built in C language context (for example, by + output_func_start_profiler). + +Wed Nov 19 10:39:27 1997 Jason Merrill + + * decl.c (make_implicit_typename): New fn. + (lookup_name_real): Use it. Use current_class_type as the context. + +Mon Nov 17 23:42:03 1997 Bruno Haible + + * pt.c (do_poplevel): Don't prohibit jumps into this contour. + +Mon Nov 17 02:01:28 1997 Jason Merrill + + * friend.c (do_friend): Warn about non-template friends in templates. + + * call.c (build_op_delete_call): Fix handling of inherited delete. + + * search.c (dfs_record_inheritance): Ignore template type parms. + +Sat Nov 15 00:30:51 1997 Jason Merrill + + * call.c (build_new_op): Fix copy error. + (build_op_new_call): New fn. + (build_op_delete_call): New fn. + * cp-tree.h: Declare them. + * init.c (build_new): Use them. Support placement delete. + (build_x_delete): Use build_op_delete_call. + (build_delete): Likewise. + * decl2.c (delete_sanity): Likewise. + (coerce_delete_type): Don't complain about placement delete. + +Thu Nov 13 01:52:36 1997 Jason Merrill + + * call.c (build_new_function_call): Remove unused 'obj' parm. + * cp-tree.h, typeck.c: Adjust. + + * init.c (build_new): Make the cleanup last longer. + (expand_vec_init): Call do_pending_stack_adjust. + +Wed Nov 12 11:04:33 1997 Jason Merrill + + * pt.c (do_type_instantiation): Fix typo. + (mark_class_instantiated): If we support one_only but not weak + symbols, don't mark this as known. + + * init.c (build_new): Handle vec delete in EH cleanup. + +Wed Nov 12 08:11:55 1997 Benjamin Kosnik + + * call.c (build_method_call): Call complete_type before checking + for destructor. + +Sun Nov 9 01:29:55 1997 Jim Wilson (wilson@cygnus.com) + + * decl.c (add_block_current_level): Delete. + * init.c (build_vec_delete_1): Delete build_block and + add_block_current_level calls. + +Wed Nov 12 00:48:16 1997 Jason Merrill + + * init.c (build_new): Handle freeing allocated memory when the + constructor throws. + + * call.c (build_new_method_call): Fix flags arg. + + * pt.c (do_type_instantiation): Don't try to instantiate + member templates. + (mark_decl_instantiated): If we support one_only but not + weak symbols, mark this one_only. + * decl2.c (import_export_vtable): Don't defer handling of vtables + if MULTIPLE_SYMBOL_SPACES. + +Tue Nov 11 12:02:12 1997 Jason Merrill + + * except.c (expand_end_catch_block): Lose call to __sjpopnthrow. + +Tue Nov 11 02:53:44 1997 Jason Merrill + + * except.c (do_pop_exception): Return a value. + +Mon Nov 10 20:25:31 1997 Jason Merrill + + * call.c (build_new_method_call): Handle getting a + TEMPLATE_ID_EXPR around a TEMPLATE_DECL. Don't look for a field + if we got template parms. + * typeck.c (build_x_function_call): Remember the TEMPLATE_ID_EXPR, + not just the args. + * decl2.c (build_expr_from_tree): Tweak last change. + * pt.c (tsubst_copy): Use get_first_fn instead of TREE_VALUE. + (maybe_fold_nontype_arg): Split out from tsubst_copy. + * tree.c (get_first_fn): Just return a TEMPLATE_ID_EXPR. + +Mon Nov 10 20:08:38 1997 Kriang Lerdsuwanakij + + * pt.c (tsubst_copy): Handle explicit template arguments in + function calls. + * typeck.c (build_x_function_call): Likewise. + * decl2.c (build_expr_from_tree): Lookup function name if it + hasn't been done. + + * pt.c (tsubst): Instantiate template functions properly when + template parameter does not appear in function arguments and return + type. + (comp_template_args): Handle member templates required by tsubst. + +Mon Nov 10 20:08:38 1997 Jason Merrill + + * decl.c (grokdeclarator): Tweak conditions for pedwarn in + previous change. + +Mon Nov 10 20:08:29 1997 Bruno Haible + + * pt.c (coerce_template_parms): Tweak error message. + + * decl.c (grokdeclarator): If -Wreturn-type, warn everytime a + return type defaults to `int', even if there are storage-class + specifiers. + +Mon Nov 10 03:04:20 1997 Jason Merrill + + Complete nested exception support. + * except.c (do_pop_exception): Split out... + (push_eh_cleanup): From here. Handle the EH region by hand. + (expand_start_catch_block): Add a new level for the catch parm. + Move the rethrow region outside the two cleanup regions. + Protect the initializer for the catch parm with terminate. + (expand_end_catch_block): Likewise. End the region for the eh_cleanup. + * exception.cc (__cp_pop_exception): Now takes two parms. Handle + popping off the middle of the stack. + * tree.c (lvalue_p, real_lvalue_p): Handle TRY_CATCH_EXPR, + WITH_CLEANUP_EXPR, and UNSAVE_EXPR. + (build_cplus_new): Only wrap CALL_EXPRs. + * init.c (expand_default_init): Handle a TRY_CATCH_EXPR around + the constructor call. + +Sun Nov 9 18:00:26 1997 Richard Kenner + + * Make-lang.in (c++.distdir): Make inc subdirectory. + +Fri Nov 7 11:57:28 1997 Jason Merrill + + * decl2.c (finish_file): Put back some code. + +Thu Nov 6 11:28:14 1997 Jason Merrill + + * decl2.c (finish_file): Remove redundant code. + * method.c (emit_thunk): Don't let the backend defer generic thunks. + +Wed Nov 5 23:52:50 1997 Jason Merrill + + * except.c (call_eh_info): Split out... + (push_eh_info): From here. + (expand_builtin_throw): Use it. + (expand_start_catch_block): Move region start back. + +Tue Nov 4 13:45:10 1997 Doug Evans + + * lex.c (MULTIBYTE_CHARS): #undef if cross compiling. + (real_yylex): Record wide strings using target endianness, not host. + +1997-11-03 Brendan Kehoe + + * repo.c (rindex): Add decl unconditionally. + (get_base_filename, open_repo_file): Don't cast rindex. + * xref.c (rindex): Add decl unconditionally. + (index): Remove unused decl. + (open_xref_file): Don't cast rindex. + +Sun Nov 2 15:04:12 1997 Jason Merrill + + * class.c (build_vbase_path): Propagate the result type properly. + +1997-11-01 Brendan Kehoe + + * except.c (expand_builtin_throw) [!DWARF2_UNWIND_INFO]: Replace + remaining use of saved_throw_type with a call to get_eh_type. + +1997-10-31 Brendan Kehoe + + * lex.c (FILE_NAME_NONDIRECTORY): Delete macro. + (file_name_nondirectory): New function, doing the same as the macro. + (set_typedecl_interface_info): Use it instead of the macro. + (check_newline): Likewise. + (handle_cp_pragma): Likewise. + + * repo.c (get_base_filename): Cast result of rindex to char*. + (open_repo_file): Likewise. + * xref.c (open_xref_file): Likewise. + * error.c (dump_char): Make its arg int, not char. + + * except.c (push_eh_info): Pass the number of fields - 1 down, not + the exact number of fields. + +Fri Oct 31 01:47:57 1997 Jason Merrill + + Support for nested exceptions. + * tinfo2.cc (__is_pointer): New fn. + * exception.cc (struct cp_eh_info): Define. + (__cp_exception_info, __uncatch_exception): New fns. + (__cp_push_exception, __cp_pop_exception): New fns. + * except.c: Lose saved_throw_{type,value,cleanup,in_catch}. + Lose empty_fndecl. + (init_exception_processing): Likewise. __eh_pc is now external. + (push_eh_info): New fn. + (get_eh_{info,value,type,caught}): New fns. + (push_eh_cleanup): Just call __cp_pop_exception. + (expand_start_catch_block): Use push_eh_info. Start the eh region + sooner. + (expand_end_eh_spec): Use push_eh_info. + (expand_throw): Call __cp_push_exception to set up the exception info. + Just pass the destructor or 0 as the cleanup. Call __uncatch_exception + when we rethrow. + (expand_builtin_throw): Don't refer to empty_fndecl. + +Thu Oct 23 02:01:30 1997 Jason Merrill + + * pt.c (instantiate_decl): SET_DECL_IMPLICIT_INSTANTIATION on new decl. + +1997-10-22 Brendan Kehoe + + * method.c (build_template_parm_names, build_decl_overload_real): + Add static to definitions. + * pt.c (add_to_template_args, note_template_header, + processing_explicit_specialization, type_unification_real): Likewise. + ({determine,check}_explicit_specialization): Use a single string for + error messages. + +Mon Oct 20 12:06:34 1997 Jason Merrill + + * except.c (expand_exception_blocks): Call do_pending_stack_adjust. + (expand_end_catch_block): Likewise. + (expand_end_eh_spec): Likewise. + +Mon Oct 20 11:44:20 1997 Mark Mitchell + + * decl.c (duplicate_decls): Handle template specializations + correctly. + * error.c (dump_function_name): Fix printing of specializations of + member functions that are not member templates. + * cp-tree.h (processing_specialization): Make global. + * pt.c (processing_specialization): Likewise. + * lex.c (cons_up_default_function): Save and restore + processing_specialization to avoid confusion. + +Mon Oct 20 10:52:22 1997 Jason Merrill + + * decl.c (init_decl_processing): Give null_node unknown* type. + * typeck.c (comp_target_types): Handle UNKNOWN_TYPE. + (common_type): Likewise. + * error.c (args_as_string): Recognize null_node. + +Sun Oct 19 09:13:01 1997 Richard Kenner + + * typeck.c (rationalize_conditional_expr): Handle {MIN,MAX}_EXPR. + (unary_complex_lvalue): Call it for {MIN,MAX}_EXPR. + + * decl.c (init_decl_processing): Call using_eh_for_cleanups. + + * Make-lang.in (g++): Include prefix.o. + +Thu Oct 16 15:31:09 1997 Judy Goldberg + + * pt.c (determine_explicit_specialization): Initialize "dummy" + to keep Purify quiet. + +Thu Oct 16 00:14:48 1997 Jason Merrill + + * method.c (build_overload_value): Handle TEMPLATE_CONST_PARMs here. + (build_overload_int): Not here. + +Wed Oct 15 00:35:28 1997 Mike Stump + + * class.c (build_type_pathname): Remove. + (prepare_fresh_vtable): Fix problem with complex MI vtable names. + +1997-10-14 Brendan Kehoe + + * parse.y (unary_expr): Give a pedwarn if someone tries to use the + &&label GNU extension. + +Tue Oct 14 12:01:00 1997 Mark Mitchell + + * decl.c (pushtag): Unset DECL_ASSEMBLER_NAME before setting it, + so as to avoid incorrect manglings. + * method.c (build_decl_overload_real): Don't mangle return types + for constructors. + +Tue Oct 14 11:46:14 1997 Jason Merrill + + * cp-tree.h (scratchalloc, build_scratch_list, make_scratch_vec, + scratch_tree_cons): Define as macros for now. + * call.c, class.c, cvt.c, decl.c, decl2.c, except.c, expr.c, init.c, + lex.c, method.c, parse.y, pt.c, rtti.c, search.c, tree.c, typeck.c, + typeck2.c: Use them and the expression_obstack variants. + +Mon Oct 13 17:41:26 1997 Benjamin Kosnik + + * decl.c (store_return_init): Allow classes with explicit ctors to + be used with the named return values extension. + +Fri Oct 10 12:21:11 1997 Jason Merrill + + * pt.c (instantiate_decl): Fix previous change. + +Thu Oct 9 12:08:21 1997 Jason Merrill + + * pt.c (tsubst): Fix thinko. + (instantiate_decl): Really use the original template. + + * call.c (build_new_method_call): Use simple constructor_name for + error messages. + +Wed Oct 8 22:44:42 1997 Jeffrey A Law + + * method.c (build_underscore_int): Don't use ANSI specific + features. + +Wed Oct 8 00:18:22 1997 Jason Merrill + + * decl2.c (finish_prevtable_vardecl): Check DECL_REALLY_EXTERN + for our key method; it might have been inlined by -O3. + +Tue Oct 7 23:00:12 1997 Mark Mitchell + + * decl.c (make_typename_type): Do not try to call lookup_field for + non-aggregate types. + +Tue Oct 7 22:52:10 1997 Jason Merrill + + * typeck.c (build_reinterpret_cast): Tweak. + +Tue Oct 7 22:45:31 1997 Alexandre Oliva + + * typeck.c (build_reinterpret_cast): Converting a void pointer + to function pointer with a reinterpret_cast produces a warning + if -pedantic is issued. + +Tue Oct 7 22:43:43 1997 Bruno Haible + + * typeck.c (c_expand_return): Don't warn about returning a + reference-type variable as a reference. + +Tue Oct 7 21:11:22 1997 Jason Merrill + + * method.c (build_static_name): Fix typo. + +1997-10-07 Brendan Kehoe + + * decl.c (duplicate_decls): Make sure DECL_LANG_SPECIFIC is set on + OLDDECL before we try to do DECL_USE_TEMPLATE. + +Tue Oct 7 00:48:36 1997 Jason Merrill + + * decl.c (duplicate_decls): Don't warn about template instances. + + * typeck.c (mark_addressable): Lose ancient code that unsets + DECL_EXTERNAL. + + * pt.c (do_decl_instantiation): Lose support for instantiating + non-templates. + + * call.c (build_new_function_call): Fix handling of null explicit + template args. + (build_new_method_call): Likewise. + +Mon Oct 6 23:44:34 1997 Mark Mitchell + + * method.c (build_underscore_int): Fix typo. + +1997-10-06 Brendan Kehoe + + * tree.c (print_lang_statistics): #if 0 call to + print_inline_obstack_statistics until its definition is checked in. + +Mon Oct 6 09:27:29 1997 Jason Merrill + + * decl2.c (finish_file): Move dump_tree_statistics to end. + + * pt.c (instantiate_decl): Look for the original template. + (tsubst): Set DECL_IMPLICIT_INSTANTIATION on partial instantiations + of member templates. + +Wed Oct 1 08:41:38 1997 Jason Merrill + + * Makefile.in (g++FAQ.*): New rules. + (CONFLICTS): Update. + * g++FAQ.texi: Moved from libg++. + + * parse.y (PFUNCNAME): Only specify the type once. + +1997-10-01 Brendan Kehoe + + * lex.c (real_yylex): Clean up the code to fully behave the way + the c-lex.c parser does for complex and real numbers. + +Tue Sep 30 08:51:36 1997 Jason Merrill + + * method.c (build_decl_overload_real): Reformat. + +Tue Sep 30 00:18:26 1997 Jason Merrill + + * method.c (synthesize_method): If at_eof, determine our linkage. + +1997-09-29 Paul Eggert + + * lex.c (real_yylex): Treat `$' just like `_', except issue a + diagnostic if !dollars_in_ident or if pedantic. + + * lang-specs.h (@c++): -ansi no longer implies -$. + + * decl2.c (lang_decode_option): + -traditional and -ansi now do not mess with + dollars_in_ident. + +Mon Sep 29 19:57:51 1997 H.J. Lu + + * Makefile.in (parse.o, decl.o): Also depend on + $(srcdir)/../except.h $(srcdir)/../output.h. + (decl2.o): Also depend on $(srcdir)/../expr.h ../insn-codes.h + $(srcdir)/../except.h $(srcdir)/../output.h. + (typeck.o, init.o): Also depend on $(srcdir)/../expr.h + ../insn-codes.h. + + * call.c, cp-tree.h, decl.c, tree.c: Finish prototyping. + + * expr.c (cplus_expand_expr): Make it static. + + * decl2.c, init.c, typeck.c: Include "expr.h". + (expand_expr): Use proper values when calling the function. + +Mon Sep 29 11:05:54 1997 Alexandre Oliva + + * lang-options.h: New -Wold-style-cast flag. + * cp-tree.h (warn_old_style_cast): New variable. + * decl2.c (warn_old_style_cast): Likewise. + (lang_decode_option): Support -Wold-style-cast. + (reparse_absdcl_as_casts): Produce old-style-cast warning. + +Mon Sep 29 09:20:53 1997 Benjamin Kosnik + + * decl.c (cp_finish_decl): Allow expand_aggr_init to set + TREE_USED, reset value based on already_used. + + * init.c (expand_member_init): Revert change. + +Mon Sep 29 08:57:53 1997 Jason Merrill + + * cp-tree.h, decl.c, decl2.c, pt.c: + Lose DECL_C_STATIC and DECL_PUBLIC. Don't pretend statics are public. + + * decl2.c (lang_decode_option): Add missing ;. + +Sat Sep 27 16:22:48 1997 Jason Merrill + + * friend.c (do_friend): Disable injection for all template-derived + decls. + * decl2.c (lang_decode_option): Handle -fguiding-decls. + * parse.y (notype_template_declarator): New nonterminal. + (direct_notype_declarator): Use it. + (complex_direct_notype_declarator): Likewise. + (object_template_id): Accept any kind of identifier after TEMPLATE. + (notype_qualified_id): Don't add template declarators here. + +Sat Sep 27 16:21:58 1997 Mark Mitchell + + * call.c (add_template_candidate): Add explicit_targs parameter. + (build_scoped_method_call): Use it. + (build_overload_call_real): Likewise. + (build_user_type_conversion_1): Likewise. + (build_new_function_call): Likewise. + (build_object_call): Likewise. + (build_new_op): Likewise. + (build_new_method_call): Likewise. + (build_new_function_call): Handle TEMPLATE_ID_EXPR. + (build_new_method_call): Likewise. + + * class.c (finish_struct_methods): Add specialization pass to + determine which methods were specializing which other methods. + (instantiate_type): Handle TEMPLATE_ID_EXPR. + + * cp-tree.def (TEMPLATE_ID_EXPR): New tree code. + + * cp-tree.h (name_mangling_version): New variable. + (flag_guiding_decls): Likewise. + (build_template_decl_overload): New function. + (begin_specialization): Likewise. + (reset_specialization): Likewise. + (end_specialization): Likewise. + (determine_explicit_specialization): Likewise. + (check_explicit_specialization): Likewise. + (lookup_template_function): Likewise. + (fn_type_unification): Add explicit_targs parameter. + (type_unification): Likewise. + + * decl.c (duplicate_decls): Add smarts for explicit + specializations. + (grokdeclarator): Handle TEMPLATE_ID_EXPR, and function + specializations. + (grokfndecl): Call check_explicit_specialization. + + * decl2.c (lang_decode_option): Handle -fname-mangling-version. + (build_expr_from_tree): Handle TEMPLATE_ID_EXPR. + (check_classfn): Handle specializations. + + * error.c (dump_function_name): Print specialization arguments. + + * friend.c (do_friend): Don't call pushdecl for template + instantiations. + + * init.c (build_member_call): Handle TEMPLATE_ID_EXPR. + + * lang-options.h: Add -fname-mangling-version, -fguiding-decls, + and -fno-guiding-decls. + + * lex.c (identifier_type): Return PFUNCNAME for template function + names. + + * method.c (build_decl_overload_real): New function. + (build_template_parm_names): New function. + (build_overload_identifier): Use it. + (build_underscore_int): New function. + (build_overload_int): Use it. Add levels for template + parameters. + (build_overload_name): Likewise. Also, handle TYPENAME_TYPEs. + (build_overload_nested_names): Handle template type parameters. + (build_template_decl_overload): New function. + + * parse.y (YYSTYPE): New ntype member. + (nested_name_specifier): Use it. + (nested_name_specifier_1): Likewise. + (PFUNCNAME): New token. + (template_id, object_template_id): New non-terminals. + (template_parm_list): Note specializations. + (template_def): Likewise. + (structsp): Likewise. + (fn.def2): Handle member template specializations. + (component_decl_1): Likewise. + (direct_notype_declarator): Handle template-ids. + (component_decl_1): Likewise. + (direct_notype_declarator): Handle template-ids. + (primary): Handle TEMPLATE_ID_EXPR, and template-ids. + + * pt.c (processing_specializations): New variable. + (template_header_count): Likewise. + (type_unification_real): New function. + (processing_explicit_specialization): Likewise. + (note_template_header): Likewise. + (is_member_template): Handle specializations. + (end_template_decl): Call reset_specialization. + (push_template_decl): Handle member template specializations. + (tsubst): Likewise. + (tsubst_copy): Handle TEMPLATE_ID_EXPR. + (instantiate_template): Handle specializations. + (instantiate_decl): Likewise. + (fn_type_unification): Handle explicit_targs. + (type_unification): Likewise. Allow incomplete unification + without an error message, if allow_incomplete. + (get_bindings): Use new calling sequence for fn_type_unification. + + * spew.c (yylex): Handle PFUNCNAME. + + * tree.c (is_overloaded_fn): Handle TEMPLATE_ID_EXPR. + (really_overloaded_fn): Likewise. + (get_first_fn): Handle function templates. + + * typeck.c (build_x_function_call): Use really_overloaded_fn. + Handle TEMPLATE_ID_EXPR. + (build_x_unary_op): Likewise. + (build_unary_op): Likewise. + (mark_addressable): Templates whose address is taken are marked + as used. + +1997-09-25 Andreas Schwab + + * decl.c (init_decl_processing): Declare __builtin_constant_p as + accepting any kind of type, not only int. + +Fri Sep 26 00:22:56 1997 Jason Merrill + + * search.c (get_matching_virtual): Notice virtual bases when sorrying + about covariant returns. + + * parse.y (member_init): Also imply typename here. Remove ancient + extension for initializing base members. + +Thu Sep 25 11:11:13 1997 Jason Merrill + + Handle multi-level typenames and implicit typename in base list. + * parse.y (typename_sub{,[0-2]}): New rules. + (structsp, rule TYPENAME_KEYWORD): Use typename_sub. + (nonnested_type): New rule. + (complete_type_name): Use it. + (base_class.1): Use typename_sub and nonnested_type. + (nested_name_specifier): Don't elide std:: here. + * decl.c (make_typename_type): Handle getting a type for NAME. + (lookup_name_real): Turn std:: into :: here. + + Rvalue conversions were removed in London. + * call.c (is_subseq): Don't consider lvalue transformations. + (build_conv): LVALUE_CONV and RVALUE_CONV get IDENTITY_RANK. + (joust): Re-enable ?: kludge. + +1997-09-22 Brendan Kehoe + + * decl.c (start_function): Up warning of no return type to be a + pedwarn. + +Mon Sep 22 14:15:34 1997 Benjamin Kosnik + + * init.c (expand_member_init): Don't set TREE_USED. + * decl.c (cp_finish_decl): Mark decls used if type has TREE_USED + set,don't clear TREE_USED wholesale. + +Sat Sep 20 15:31:00 1997 Jason Merrill + + * call.c (build_over_call): Do require_complete_type before + build_cplus_new. + +Thu Sep 18 16:47:52 1997 Jason Merrill + + * search.c (lookup_field): Call complete_type in all cases. + + * decl.c (finish_function): Just warn about flowing off the end. + +Wed Sep 17 10:31:25 1997 Jason Merrill + + * decl.c (grokparms): Don't bash a permanent list node if we're + in a function. + +1997-09-17 Brendan Kehoe + + * Makefile.in (CONFLICTS): Fix s/r conflict count to 18. + +Tue Sep 16 14:06:56 1997 Jason Merrill + + * call.c (build_new_op): Give better error for syntactically + correct, but semantically invalid, use of undeclared template. + + * call.c (compare_qual): Handle pmfs. + + * decl.c (store_parm_decls): last_parm_cleanup_insn is the insn + after the exception spec. + +Mon Sep 15 11:52:13 1997 Jason Merrill + + * call.c (null_ptr_cst_p): Integer type, not integral type. + + * call.c (joust): Disable warnings until they can be moved to the + right place. + +Fri Sep 12 16:11:13 1997 Per Bothner + + * Makefile.in, config-lang.in: Convert to autoconf. + +Thu Sep 11 17:14:55 1997 Jason Merrill + + * decl.c (lookup_name_real): Add implicit 'typename' to types from + base classes. + + * pt.c (most_specialized_class): Fix typo. + (tsubst): Move constant folding to TREE_VEC case. + +Thu Sep 11 10:08:45 1997 Mark Mitchell + + * pt.c (do_poplevel): Don't warn about unused local variables + while processing_template_decl since we don't always know whether + or not they will need constructing/destructing. + + * pt.c (uses_template_parms): Check the values of an enumeration + type to make sure they don't depend on template parms. + + * decl.c (make_typename_type): Don't lookup the field if the + context uses template parms, even if we're not + processing_template_decl at the moment. + + * pt.c (coerce_template_parms): Avoid looking at the + TYPE_LANG_DECL portion of a typename type, since there won't be + one. + (tsubst): Do constant folding as necessary to make sure that + arguments passed to lookup_template_class really are constants. + +Wed Sep 10 11:21:55 1997 Jason Merrill + + * except.c (expand_builtin_throw): #ifndef DWARF2_UNWIND_INFO. + * decl2.c (finish_file): Only register exception tables if we + need to. + + * decl.c (init_decl_processing): Add __builtin_[fs]p. + +Tue Sep 9 19:49:38 1997 Jason Merrill + + * pt.c (unify): Just return 0 for a TYPENAME_TYPE. + +Tue Sep 9 17:57:25 1997 Mark Mitchell + + * error.c (dump_decl): Avoid crashing when presented with a + uninitialized constant, as can occur with a template parameter. + (dump_expr): Make sure that there are enough levels of + current_template_parms before we start diving through them. + +1997-09-09 Brendan Kehoe + + * typeck.c (build_indirect_ref): Heed FLAG_VOLATILE similar to + c-typeck.c. + +Tue Sep 9 09:36:39 1997 Benjamin Kosnik + + * except.c (expand_throw): Call build_delete for all + exception types, not just objects with destructors. + +Mon Sep 8 02:33:20 1997 Jody Goldberg + + * decl.c (current_local_enum): Remove static. + * pt.c (tsubst_enum): Save and restore value of current_local_enum + in case template is expanded in enum decl. + (instantiate_class_template): Use new tsubst_enum signature. + (tsubst_expr): Likewise. + +Mon Sep 8 01:21:43 1997 Mark Mitchell + + * pt.c (begin_member_template_processing): Take a function as + argument, not a set of template arguments. Use the template + parameters, rather than the arguments. Handle non-type parameters + correctly. Push a binding level for the parameters so that multiple + member templates using the same parameter names can be declared. + (end_member_template_processing): Pop the binding level. + (push_template_decl): Mark member templates as static when + appropriate. + + * lex.c (do_pending_inlines): Pass the function, not its template + arguments, to begin_member_template_processing. + (process_next_inline): Likewise. + (do_pending_defargs): Likewise. + + * error.c (dump_expr): Obtain the correct declaration for a + TEMPLATE_CONST_PARM. + + * call.c (add_template_conv_candidate): New function. + (build_object_call): Handle member templates, as done in the other + build_ functions. + +Sat Sep 6 10:20:27 1997 Mark Mitchell + + * decl.c (replace_defag): Undo previous change. + * lex.c (do_pending_defargs): Deal with member templates. + + * pt.c (is_member_template): Avoid crashing when passed a + non-function argument. + +Fri Sep 5 17:27:38 1997 Jason Merrill + + * class.c (grow_method): Remove check for redeclaration. + +Fri Sep 5 01:37:17 1997 Mark Mitchell + + * cp-tree.h (INNERMOST_TEMPLATE_PARMS): New macro. + (DECL_INNERMOST_TEMPLATE_PARMS): Likewise. + (PRIMARY_TEMPLATE_P): Use it. + * call.c (build_overload_call_real): Use it. + * class.c (instantiate_type): Likewise. + * decl.c (decls_match): Likewise. + * method.c (build_overload_identifier): Likewise. + * pt.c (push_template_decl): Likewise. + (classtype_mangled_name): Likewise. + (lookup_template_class): Likewise. + + * cp-tree.h (DECL_NTPARMS): Change name from DECL_NT_PARMS to + DECL_NTPARMS to conform to usage elsewhere. + * call.c (add_template_candidate): Likewise. + * class.c (instantiate_type): Likewise. + * pt.c (instantiate_template): Likewise. + (get_bindings): Likewise. + + * class.c (grow_method): Use DECL_FUNCTION_TEMPLATE_P instead of + is_member_template. + + * pt.c (unify): Undo changes to allow multiple levels of template + parameters. + (type_unification): Likewise. + (fn_type_unification): Likewise. + (get_class_bindings): Likewise. + * cp-tree.h (Likewise). + + * decl.c (replace_defarg): Check that the type of the default + parameter does not invlove a template type before complaining + about the initialization. + + * error.c (dump_expr): Deal with template constant parameters in + member templates correctly. + + * pt.c (is_member_template): Deal with class specializations + correctly. + (tsubst): Handle "partial instantiation" of member templates + correctly. + +Wed Sep 3 12:30:24 1997 Mark Mitchell + + * pt.c (type_unification): Change calling sequence to allow for + multiple levels of template parameters. + (tsubst_expr): Likewise. + (tsubst): Likewise. + (tsubst_copy): Likewise. + (instantiate_template): Likewise. + (unify): Likewise. + * call.c (build_overload_call_real): Use it. + (add_builtin_candidate): Use it. + (build_new_method_call): Use it. + * class.c (instantiate_type): Use it. + * decl.c (grokdeclarator): Use it. + * decl2.c (finish_file): Use it. + * method.c (build_overload_identifier): Use it. + + * call.c (add_template_candidate): Add additional parameter for + the function return type. Call fn_type_unification istead of + type_unification. + (build_user_type_conversion_1): Handle member templates. + (build_new_function_call): Likewise. + (build_new_op): Likewise. + (build_new_method_call): Likewise. + + * class.c (grow_method): Don't give an error message indicating + that two member templates with the same name are ambiguous. + (finish_struct): Treat member template functions just like member + functions. + + * cp-tree.h (check_member_template): Add declaration. + (begin_member_template_processing): Likewise. + (end_member_template_processing): Likewise. + (fn_type_unification): Likewise. + (is_member_template): Likewise. + (tsubst): Change prototype. + (tsubst_expr): Likewise. + (tsubst_copy): Likewise. + (instantiate_template): Likewise. + (get_bindings): Likewise. + + * decl.c (decls_match): Handle multiple levels of template + parameters. + (pushdecl): Handle template type params just like other type + declarations. + (push_class_level_binding): Return immediately if the + class_binding_level is NULL. + (grokfndecl): If check_classfn() returns a member_template, use + the result of the template, not the template itself. + + * decl2.c (check_member_template): New function. Check to see + that the entity declared to be a member template can be one. + (check_classfn): Allow redeclaration of member template functions + with different types; the new functions can be specializations or + explicit instantiations. + + * error.c (dump_decl): Handle multiple levels of template + parameters. + (dump_function_decl): Update to handle function templates. + + * lex.c (do_pending_inlines): Set up template parameter context + for member templates. + (process_next_inline): Likewise. + + * method.c (build_overload_identifier): Adjust for multiple levels + of template parameters. + + * parse.y (fn.def2): Add member templates. + (component_decl_1): Likewise. + + * pt.c (begin_member_template_processing): New function. + (end_member_template_processing): Likewise. + (is_member_template): Likewise. + (fn_type_unification): Likewise. + (current_template_parms): Return a vector of all the template + parms, not just the innermost level of parms. + (push_template_decl): Deal with the possibility of member + templates. + (lookup_template_class): Likewise. + (uses_template_parms): Likewise. + (tsubst): Modify processing to TEMPLATE_TYPE_PARM and + TEMPLATE_CONST_PARM to deal with multiple levels of template + arguments. Add processing of TEMPLATE_DECL to produce new + TEMPLATE_DECLs from old ones. + (do_decl_instantiation): Handle member templates. + + * search.c (lookup_fnfields_1): Handle member template conversion + operators. + + * tree.c (cp_tree_equal): Check the levels, as well as the + indices, of TEMPLATE_CONST_PARMs. + + * typeck.c (comptypes): Check the levels, as well as the indices, + fo TEMPLATE_TYPE_PARMs. + (build_x_function_call): Treat member templates like member + functions. + +Wed Sep 3 11:09:25 1997 Jason Merrill + + * typeck.c (c_expand_return): Always convert_for_initialization + before checking for returning a pointer to local. + + * pt.c (type_unification): If strict and the function parm doesn't + use template parms, just compare types. + +Wed Sep 3 10:35:49 1997 Klaus Espenlaub + + * method.c (build_overloaded_value): Replace direct call + to the floating point emulator with REAL_VALUE_TO_DECIMAL macro. + +Wed Sep 3 00:02:53 1997 Jason Merrill + + * typeck.c (convert_arguments): Don't arbitrarily choose the first + of a set of overloaded functions. + +Tue Sep 2 12:09:13 1997 Jason Merrill + + * lex.c (real_yylex): Don't elide __FUNCTION__. + + * method.c (build_overload_value): Add in_template parm. + (build_overload_int): Likewise. + (build_overload_identifier): Pass it. + + * decl.c (duplicate_decls): Don't bash a previous template + definition with a redeclaration. + + * pt.c (unify): float doesn't match double. + + * pt.c (do_type_instantiation): Handle getting a _TYPE or a + TYPE_DECL. Handle getting non-template types. + * parse.y (explicit_instantiation): Use typespec instead of + aggr template_type. + +Tue Sep 2 10:27:08 1997 Richard Henderson + + * typeck.c (build_ptrmemfunc1): Clean up ptr->int cast warnings. + +Mon Sep 1 13:19:04 1997 Eugene Mamchits + + * call.c (add_builtin_candidate): Add missing TREE_TYPE. + (compare_ics): Likewise. + +Mon Sep 1 13:19:04 1997 Jason Merrill + + * call.c (joust): Warn about choosing one conversion op over + another because of 'this' argument when the other return type is + better. + (source_type): New fn. + + * call.c (build_new_op): Strip leading REF_BIND from first operand + to builtin operator. + + * decl2.c (mark_vtable_entries): Mark abort_fndecl as used when we + use its RTL. + +Thu Aug 28 09:45:23 1997 Jason Merrill + + * call.c (null_ptr_cst_p): Remove support for (void*)0. + +Wed Aug 27 02:03:34 1997 Jeffrey A Law + + * typeck.c (expand_target_expr): Make definition match declaration. + + * class.c (get_basefndecls): Make definition match declaration. + +Mon Aug 25 14:30:02 1997 Jason Merrill + + * input.c (sub_getch): Eventually give up and release the input file. + + * decl.c (cp_finish_decl): If #p i/i, put inline statics in the + right place. + + * call.c (joust): Tweak message. + +Sat Aug 23 18:02:59 1997 Mark Mitchell + + * error.c (type_as_string): Put const/volatile on template type + parameters where appropriate. + +Sat Aug 23 17:47:22 1997 Jeffrey A Law + + * call.c (strictly_better): Make arguments unsigned ints. + +Thu Aug 21 18:48:44 1997 Jason Merrill + + * lex.c (real_yylex): Refer to __complex instead of complex. + +Thu Aug 21 22:25:46 1997 J"orn Rennecke + + * lex.c (real_yylex): Don't use getc directly. + +Wed Aug 20 17:25:08 1997 Jason Merrill + + * call.c (is_subseq): Don't try to be clever. + +Wed Aug 20 03:13:36 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * parse.y, pt.c: Include "except.h". + * call.c, class.c, class.h, cp-tree.h, cvt.c, decl.c, decl2.c, + error.c, except.c, expr.c, friend.c, g++spec.c, init.c, input.c, + lex.c, lex.h, method.c, parse.y, pt.c, repo.c, rtti.c, search.c, + sig.c, spew.c, tree.c, typeck.c, typeck2.c, xref.c: Finish + prototyping. + +Wed Aug 20 01:34:40 1997 Jason Merrill + + * decl2.c (mark_vtable_entries): Instead of replacing pure + virtuals with a reference to __pure_virtual, copy the decl and + change the RTL. + +Tue Aug 19 02:26:07 1997 Jason Merrill + + * pt.c (lookup_nested_type_by_name): Handle typedef wierdness. + + * typeck2.c (my_friendly_abort): Report bugs to egcs-bugs@cygnus.com. + + * pt.c (instantiate_class_template): Call repo_template_used + before finish_prevtable_vardecl. + + * call.c (is_subseq): New fn. + (compare_ics): Use it. + + * repo.c (finish_repo): Don't crash on no args. + + * parse.y (named_complex_class_head_sans_basetype): Handle + explicit global scope. + * decl2.c (handle_class_head): New fn. + + * pt.c (unify): Add CONST_DECL case. + +Thu Aug 14 10:05:13 1997 Brendan Kehoe + + * rtti.c (permanent_obstack): Fix decl to not be a pointer. + + * cp-tree.h (report_type_mismatch): Add prototype. + * call.c (build_overload_call_real): Remove erroneous fourth + argument to report_type_mismatch. + (build_user_type_conversion_1): Remove erroneous second arg to + tourney. + (build_new_function_call): Likewise. + (build_object_call): Likewise. + (build_new_op): Likewise. + (build_new_method_call): Likewise. + +Wed Aug 13 19:19:25 1997 Jason Merrill + + * error.c (dump_decl): Don't bother processing a function with no + DECL_LANG_SPECIFIC. + + * method.c (emit_thunk): Call init_function_start in the macro case. + +Wed Aug 13 10:46:19 1997 H.J. Lu (hjl@gnu.ai.mit.edu) + + * decl2.c (DEFAULT_VTABLE_THUNKS): Define to be 0 if not + defined and used to set flag_vtable_thunks. + +Tue Aug 12 20:13:57 1997 Jason Merrill + + * parse.y: Don't clear the inlines from their obstack until they've + all been processed. + + * decl.c (duplicate_decls): Don't complain about exception + specification mismatch if flag_exceptions is off. + +Mon Aug 11 15:01:56 1997 Marc Lehmann + + * Make-lang.in (c++.distclean): Remove g++.c on make distclean. + +Sun Aug 10 12:06:09 1997 Paul Eggert + + * cp-tree.h: Replace STDIO_PROTO with PROTO in include files. + * cvt.c, error.c, except.c, expr.c, friend.c, init.c, rtti.c: + Include before include files that formerly used STDIO_PROTO. + + * decl.c, g++spec.c, lex.c, method.c, repo.c: + Include "config.h" first, as per autoconf manual. + +Fri Aug 8 11:47:48 1997 Jason Merrill + + * decl.c (duplicate_decls): Tweak wording. + * lex.c (do_pending_defargs): Don't die if we see a default arg + that isn't a DEFAULT_ARG. + * error.c (dump_expr): Handle DEFAULT_ARG. + + * decl2.c (lang_decode_option): Handle -fhandle-exceptions. + * lang-options.h: Add -fhandle-exceptions. + + * class.c (build_vtable): Vtables are artificial. + (prepare_fresh_vtable): Likewise. + +Wed Aug 6 11:02:36 1997 Jason Merrill + + * cvt.c (ocp_convert): After converting to the target type, set + LOOKUP_NO_CONVERSION. + + * call.c (joust): Warn about potentially confusing promotion rules + with -Wsign-promo. + * cp-tree.h, lang-options.h, decl2.c: Support -Wsign-promo. + +Tue Aug 5 15:15:07 1997 Michael Meissner + + * exception.cc: Declare __terminate_func with noreturn attribute. + +Fri Aug 1 03:18:15 1997 Jason Merrill + + * parse.y: Break out eat_saved_input, handle errors. + (function_try_block): Use compstmt instead of compstmt_or_error. + +Thu Jul 31 17:14:04 1997 Jason Merrill + + * tree.c (build_cplus_new): Don't set TREE_ADDRESSABLE. + +Fri Jul 4 01:45:16 1997 Andreas Schwab + + * Make-lang.in (cplib2.txt, cplib2.ready): Instead of checking for + existence of cc1plus check whether $(LANGUAGES) contains C++. + +Wed Jul 30 13:04:21 1997 Andreas Schwab + + * method.c (do_build_copy_constructor): When copying an anonymous + union member loop around to handle nested anonymous unions. Use + the offset of the member relative to the outer structure, not the + union. + +Tue Jul 29 21:17:29 1997 Jason Merrill + + * call.c (resolve_args): New fn. + (build_new_function_call): Use it. + (build_object_call): Likewise. + (build_new_method_call): Likewise. + +Mon Jul 28 16:02:36 1997 Jason Merrill + + * call.c (build_over_call): tsubst all default parms from templates. + +Wed Jul 23 13:36:25 1997 Jason Merrill + + * decl.c (struct cp_function): Add static_labelno. + (push_cp_function_context): Save it. + (pop_cp_function_context): Restore it. + +Tue Jul 22 14:43:29 1997 Jason Merrill + + * typeck.c (build_component_ref_1): Convert from reference. + +Tue Jul 22 11:06:23 1997 Brendan Kehoe + + * parse.y (current_declspecs, prefix_attributes): Initialize to + NULL_TREE. + + * parse.y (initdcl0): Make sure CURRENT_DECLSPECS is non-nil + before we try to force it to be a TREE_LIST. + (decl): Make sure $1.t is non-nil. + +Sun Jul 20 11:53:07 1997 Jason Merrill + + * pt.c (uses_template_parms): Handle template first-parse codes. + + * decl.c (cp_finish_decl): Only warn about user-defined statics. + +Fri Jul 18 17:56:08 1997 Jason Merrill + + * pt.c (unify): Handle BOOLEAN_TYPE. + + * cp-tree.h: Lose PARM_DEFAULT_FROM_TEMPLATE. + * pt.c (tsubst): Don't set it. + * call.c (build_over_call): Use uses_template_parms. + +Thu Jul 17 18:06:30 1997 Jason Merrill + + * method.c (build_overload_nested_name): Use static_labelno + instead of var_labelno. + (build_qualified_name): New fn. + (build_overload_name): Split out from here. + (build_static_name): Use build_qualified_name. + * decl.c (cp_finish_decl): Statics in extern inline functions + have comdat linkage. + (start_function): Initialize static_labelno. + +Thu Jul 17 11:20:17 1997 Benjamin Kosnik + + * class.c (finish_struct_methods): Add check of warn_ctor_dtor_privacy + before "all member functions in class [] are private". + +Wed Jul 16 23:47:08 1997 Jason Merrill + + * lex.c (do_scoped_id): convert_from_reference. + * init.c (build_offset_ref): Likewise. + +Wed Jul 16 12:34:29 1997 Benjamin Kosnik + + * error.c (dump_expr): Check TREE_OPERAND before dump_expr_list. + +Mon Jul 14 03:23:46 1997 Jason Merrill + + * typeck.c (get_member_function_from_ptrfunc): Promote index + before saving it. + +Sun Jul 13 00:11:52 1997 Jason Merrill + + * tree.c (layout_basetypes): Move non-virtual destructor warning. + * decl.c (xref_basetypes): Remove non-virtual destructor warning. + +Sat Jul 12 12:47:12 1997 Jason Merrill + + * decl.c (grokdeclarator): Call add_defarg_fn for the function + type, too. + * lex.c (add_defarg_fn): Adjust. + (do_pending_defargs): Adjust. Don't skip the first parm. + +Fri Jul 11 01:39:50 1997 Jason Merrill + + * decl.c (build_enumerator): Global enumerators are also readonly. + + * rtti.c (build_dynamic_cast_1): Renamed from build_dynamic_cast. + (build_dynamic_cast): Call it and convert_from_reference. + + * lex.c (add_defarg_fn): New fn. + (snarf_defarg): Don't add to defarg_types. + (do_pending_defargs): Lose defarg_types. All fns we process now + have defargs. + * decl.c (grokfndecl): Call add_defarg_fn. + + * Makefile.in (CONFLICTS): Expect 18 s/r conflicts. + * cp-tree.def: Add DEFAULT_ARG. + * spew.c (yylex): Call snarf_defarg as appropriate. + * parse.y: New tokens DEFARG and DEFARG_MARKER. + (defarg_again, pending_defargs, defarg, defarg1): New rules. + (structsp): Use pending_defargs. + (parms, full_parm): Use defarg. + * lex.c (init_lex): Initialize inline_text_firstobj. + (do_pending_inlines): Never pass the obstack to feed_input. + (process_next_inline): Call end_input instead of restore_pending_input. + (clear_inline_text_obstack, reinit_parse_for_expr, do_pending_defargs, + finish_defarg, feed_defarg, snarf_defarg, maybe_snarf_defarg): New fns. + * input.c (end_input): New fn. + (sub_getch): At the end of some fed input, just keep returning EOF + until someone calls end_input. + Remove 'obstack' field from struct input_source. + * decl.c (grokparms): Handle DEFAULT_ARG. + (replace_defarg): New fn. + * cp-tree.h (DEFARG_LENGTH, DEFARG_POINTER): New macros. + +Wed Jul 9 13:44:12 1997 Jason Merrill + + * call.c (implicit_conversion): If nothing else works, try binding + an rvalue to a reference. + +Wed Jul 9 13:04:38 1997 Geoffrey Noer + + * decl.c (init_decl_processing): Fix Jun 30 patch -- move + ifndef for Cygwin32 to include SIGSEGV. + +Thu Jul 3 01:44:05 1997 Jason Merrill + + * class.c (finish_struct_1): Only complain about pointers without + copy stuff if there are any constructors. + + * rtti.c (build_dynamic_cast): Call complete_type on the types. + + * decl.c (grokfndecl): If the function we chose doesn't actually + match, die. + + * decl2.c (grokclassfn): Don't specify 'const int' for the + artificial destructor parm. + + * pt.c (type_unification): If we are called recursively, nothing + decays. + +Mon Jun 30 17:53:21 1997 Geoffrey Noer + + * decl.c (init_decl_processing): Stop trying to catch signals + other than SIGABRT since the Cygwin32 library doesn't support + them correctly yet. This fixes a situation in which g++ causes + a hang on SIGSEGVs and other such signals in our Win32-hosted + tools. + +Mon Jun 30 14:50:01 1997 Jason Merrill + + * tree.c (mapcar, case CALL_EXPR): Handle all the parse node data. + +Fri Jun 27 15:18:49 1997 Jason Merrill + + * typeck2.c (store_init_value): Always return the value if our + type needs constructing. + + * method.c (hack_identifier): Convert class statics from + reference, too. + +Thu Jun 26 11:44:46 1997 Jason Merrill + + * Make-lang.in (cplib2.ready): Add $(LANGUAGES) dependency. + +Thu Jun 19 16:49:28 1997 Mike Stump + + * typeck.c (c_expand_return): Make sure we clean up temporaries at + the end of return x; + +Thu Jun 19 12:28:43 1997 Brendan Kehoe + + * lex.c (check_for_missing_semicolon): Also check for CV_QUALIFIER. + +Tue Jun 17 18:35:57 1997 Mike Stump + + * except.c (expand_builtin_throw): Add support + -fno-sjlj-exceptions -fPIC exception handling on the SPARC. + +Mon Jun 16 01:24:37 1997 Jason Merrill + + * repo.c (extract_string): Null-terminate. + + * cp-tree.h (TI_SPEC_INFO): New macro. + (CLASSTYPE_TI_SPEC_INFO): New macro. + * pt.c (push_template_decl): Correctly determine # of template parms + for partial specs. + + * call.c (compare_ics): Really fix 'this' conversions. + + * pt.c (do_decl_instantiation): Don't crash on explicit inst of + non-template fn. + + * pt.c (push_template_decl): Complain about mismatch in # of + template parms between a class template and a member template. + +Sun Jun 15 02:38:20 1997 Jason Merrill + + * method.c (synthesize_method): You can't call + function_cannot_inline_p after finish_function. + * decl.c (finish_function): Turn on flag_inline_functions and turn + off DECL_INLINE before handing a synthesized method to the + backend. + +Thu Jun 12 17:35:28 1997 Jason Merrill + + * method.c (synthesize_method): Remove July 30 change to never set + DECL_INLINE if at_eof. + +Thu Jun 12 15:25:08 1997 Mike Stump + + * xref.c (GNU_xref_member): Ensure that the node has a + decl_lang_specific part before checking DECL_FRIEND_P. + +Thu Jun 12 12:36:05 1997 Jason Merrill + + * pt.c (instantiate_class_template): Diagnose non-class types used + as bases. + +Wed Jun 11 17:33:40 1997 Jason Merrill + + * typeck.c (build_conditional_expr): Use convert_for_initialization + instead of convert_and_check. + +Wed Jun 11 12:31:33 1997 Brendan Kehoe + + * parse.y (typespec): Don't pedwarn for typeof. + +Tue Jun 10 00:22:09 1997 Jason Merrill + + * repo.c (finish_repo): Only check changes if we would write a + repo file. + + * call.c (compare_ics): Fix handling of 'this' conversions. + + * pt.c (do_decl_instantiation): Support static data too. Rename + from do_function_instantiation. + * cp-tree.h: Adjust. + * parse.y: Adjust. + + * repo.c (extract_string): New fn. + (get_base_filename): Use it. + (init_repo): Compare old args with current args. + +Mon Jun 9 14:25:30 1997 Mike Stump + + * Makefile.in, Make-lang.in: Protect C-ls with a comment + character, idea from Paul Eggert . + +Mon Jun 9 01:52:03 1997 Jason Merrill + + * typeck.c (c_expand_return): Be more persistent in looking for + returned temps. + + * cvt.c (build_up_reference): Use NOP_EXPR for switching from + pointer to reference. + + * class.c (build_vbase_path): Don't do anything if PATH has no steps. + +Sun Jun 8 03:07:05 1997 Jason Merrill + + * init.c (build_member_call, build_offset_ref): + Use do_scoped_id instead of do_identifier. + + * cvt.c (convert): Remove bogosity. + +Sat Jun 7 20:50:17 1997 Brendan Kehoe + + * cvt.c (build_up_reference): Do checks of ARGTYPE and + TARGET_TYPE before trying to use get_binfo. + +Fri Jun 6 17:36:39 1997 Jason Merrill + + * cvt.c (build_up_reference): Call get_binfo to get access control. + + * decl2.c (import_export_decl): If we don't support weaks, leave + statics undefined. + +Fri Jun 6 15:55:49 1997 Mike Stump + + * except.c (expand_builtin_throw): Add support for machines that + cannot access globals after throw's epilogue when + -fno-sjlj-exceptions is used. + +Thu Jun 5 16:28:43 1997 Jason Merrill + + * parse.y: 'std::' becomes '::'. + * lex.c (real_yylex): Remove 'namespace' warning. + * init.c (build_member_call): Ignore 'std::'. + (build_offset_ref): Likewise. + * decl2.c (do_using_directive): Ignore 'using namespace std;'. + (do_toplevel_using_decl): Ignore 'using std::whatever'. + * decl.c (push_namespace): Just sorry. + (pop_namespace): Nop. + (init_decl_processing): Declare std namespace. + +Tue Jun 3 18:08:23 1997 Jason Merrill + + * search.c (push_class_decls): A name which ambiguously refers to + several instantiations of the same template just refers to the + template. + +Tue Jun 3 12:30:40 1997 Benjamin Kosnik + + * decl.c (build_enumerator): Fix problem with unsigned long + enumerated values being smashed to ints, causing overflow + when computing next enumerated value (for enum values around + MAX_VAL). + +Mon Jun 2 17:40:56 1997 Jason Merrill + + * typeck.c (build_component_ref): Only call mark_used on a decl. + +Thu May 29 15:54:17 1997 Brendan Kehoe + + * typeck.c (build_c_cast): Make the check for a ptr to function + more specific before possible default_conversion call. + +Thu May 29 13:02:06 1997 Mike Stump + + * except.c (expand_exception_blocks): Simplify and fix and make + sure we don't end a region in a sequence, as expand_end_bindings + doesn't like it. + +Wed May 28 17:08:03 1997 Mike Stump + + * except.c (init_exception_processing): Mark terminate as not + returning so that the optimizer can optimize better. + +Tue May 27 19:49:19 1997 Mike Stump + + * cvt.c (convert): Don't do any extra work, if we can avoid it + easily. + +Tue May 27 18:21:47 1997 Mike Stump + + * *.[chy]: Change cp_convert to ocp_convert, change convert to + cp_convert. convert is now reserved for the backend, and doesn't + have the semantics a frontend person should ever want. + +Fri May 23 10:58:31 1997 Jason Merrill + + * lang-specs.h: Define __EXCEPTIONS if exceptions are enabled. + Lose -traditional support. + +Thu May 22 15:41:28 1997 Jason Merrill + + * rtti.c (get_tinfo_var): Use TYPE_PRECISION (sizetype). + + * parse.y (self_reference): Do it for templates, too. + * class.c (pushclass): Don't overload_template_name; the alias + generated by build_self_reference serves the same purpose. + + * tree.c (list_hash): Make static, take more args. + (list_hash_lookup): Likewise. + (list_hash_add): Make static. + (list_hash_canon): Lose. + (hash_tree_cons): Only build a new node if one isn't already in the + hashtable. + (hash_tree_chain): Use hash_tree_cons. + * cp-tree.h: Adjust. + * decl.c (grokfndecl): Just check IDENTIFIER_GLOBAL_VALUE instead + of calling lookup_name. + +Wed May 21 18:24:19 1997 Jason Merrill + + * pt.c (instantiate_class_template): TYPE_VALUES for an enum + doesn't refer to the CONST_DECLs. + +Tue May 20 21:09:32 1997 Bob Manson + + * rtti.c (get_tinfo_var): Either INT_TYPE_SIZE or 32, whichever + is bigger. + (expand_class_desc): Convert the last argument to a sizetype. + +Tue May 20 13:55:57 1997 Brendan Kehoe + + * gxx.gperf (__complex, __complex__, __imag, __imag__, __real, + __real__): Add reswords. + * hash.h: Regenerate. + * lex.h (rid): Add RID_COMPLEX. + (RID_LAST_MODIFIER): Set to RID_COMPLEX. + * lex.c (init_lex): Add building of RID_COMPLEX. + (real_yylex): General cleanup in line with what c-lex.c also has, + sans the cruft for traditional; add handling of SPEC_IMAG, complex + types, and imaginary numeric constants. + * parse.y (REALPART, IMAGPART): Add tokens. + (unary_expr): Add REALPART and IMAGPART rules. + * cp-tree.h (complex_{integer,float,double,long}_type_node): Declare. + * decl.c (complex_{integer,float,double,long}_type_node): Define + types. + (init_decl_processing): Set up the types. + (grokdeclarator): Add handling of RID_COMPLEX. Set and use + DEFAULTED_INT instead of EXPLICIT_INT when we default to int type. + * call.c (build_new_op): Add REALPART_EXPR and IMAGPART_EXPR cases. + * cvt.c (cp_convert): Handle COMPLEX_TYPE. + * error.c (dump_type_prefix, dump_type, dump_type_suffix): Add + COMPLEX_TYPE case. + * method.c (build_overload_name): Add handling of the different + COMPLEX_TYPEs, prefixing them with `J'. + * pt.c (process_template_parm): Don't let them use a COMPLEX_TYPE + as a template parm. + (uses_template_parms, tsubst, unify): Add COMPLEX_TYPE case. + * tree.c (lvalue_p): Add REALPART_EXPR and IMAGPART_EXPR cases. + (mapcar): Handle COMPLEX_CST. + * typeck.c (build_binary_op_nodefault): Handle COMPLEX_TYPE. + (common_type): Add code for complex types. + (build_unary_op): Add REALPART_EXPR and IMAGPART_EXPR cases. + (convert_for_assignment): Likewise. + (mark_addressable): Add REALPART_EXPR and IMAGPART_EXPR cases. + +Mon May 19 12:26:27 1997 Jason Merrill + + * pt.c (tsubst): Don't pass the MINUS_EXPR for an array domain to + tsubst_expr, as it might try to do overload resolution. + +Sat May 17 10:48:31 1997 Jason Merrill + + * pt.c (instantiate_class_template): Oops. + +Fri May 16 14:23:57 1997 Jason Merrill + + * cp-tree.def: Add TAG_DEFN. + * pt.c (tsubst_enum): New fn. + (instantiate_class_template): Use it. + (tsubst_expr): Support TAG_DEFN. + (tsubst): Support local enums. + (tsubst_copy): Likewise. + * decl.c (finish_enum): Likewise. + (start_enum): If this is a local enum, switch to permanent_obstack. + +Wed May 14 19:08:28 1997 Mike Stump + + * decl.c (store_parm_decls): Set last_parm_cleanup_insn here. + (finish_function): Put the base init code for constructors just + after the parm cleanup insns. + (struct cp_function): Add last_parm_cleanup_insn. + (push_cp_function_context): Likewise. + (pop_cp_function_context): Likewise. + +Tue May 13 15:51:20 1997 Jason Merrill + + * pt.c (tsubst_copy): Handle BIT_NOT_EXPR. + +Wed May 7 11:17:59 1997 Brendan Kehoe + + * method.c (emit_thunk) [ASM_OUTPUT_MI_THUNK]: Build up the RTL + for THUNK_FNDECL before we switch to temporary allocation. + +Mon May 5 14:46:53 1997 Jason Merrill + + * call.c (build_new_op): Handle null arg2 for ?:. + +Thu May 1 18:26:37 1997 Mike Stump + + * except.c (expand_exception_blocks): Ensure that we flow through + the end of the exception region for the exception specification. + Move exception region for the exception specification in, so that + it doesn't protect the parm cleanup. Remove some obsolete code. + * decl.c (store_parm_decls): Likewise. + (finish_function): Likewise. + +Tue Apr 29 15:38:54 1997 Jason Merrill + + * init.c (build_new): Fix nothrow handling. + +Tue Apr 29 14:29:50 1997 Brendan Kehoe + + * init.c (emit_base_init): Don't warn about the initialization + list for an artificial member. + +Fri Apr 25 17:47:59 1997 Brendan Kehoe + + * expr.c (do_case): Handle !START case for the error msg. + +Fri Apr 25 11:55:23 1997 Jason Merrill + + * decl2.c, lang-options.h: New option -Weffc++. + * class.c, decl.c, init.c, typeck.c: Move Effective C++ warnings + to -Weffc++. + + * decl2.c (finish_prevtable_vardecl): Change NO_LINKAGE_HEURISTICS + to MULTIPLE_SYMBOL_SPACES. + +Wed Apr 23 18:06:50 1997 Jason Merrill + + * method.c (emit_thunk, generic case): Set current_function_is_thunk. + + * method.c (emit_thunk, macro case): Set up DECL_RESULT. + + * typeck.c (c_expand_return): Don't complain about returning void + to void in an artificial function. + * method.c (make_thunk): Change settings of READONLY/VOLATILE, + don't set DECL_RESULT, set DECL_ARTIFICIAL. + (emit_thunk, generic code): Also set up DECL_LANG_SPECIFIC. + +Wed Apr 23 14:43:06 1997 Mike Stump + + * init.c (init_decl_processing): Add support for setjmp/longjmp based + exception handling. + * except.c (init_exception_processing): Likewise. + (expand_end_catch_block): Likewise. + (expand_exception_blocks): Likewise. + (expand_throw): Likewise. + * exception.cc (__default_terminate): Likewise. + + * init.c (perform_member_init): Use new method of expr level + cleanups, instead of cleanups_this_call and friends. + (emit_base_init): Likewise. + (expand_aggr_vbase_init_1): Likewise. + (expand_vec_init): Likewise. + * decl.c (cp_finish_decl): Likewise. + (expand_static_init): Likewise. + (store_parm_decls): Likewise. + (cplus_expand_expr_stmt): Likewise. + * decl2.c (finish_file): Likewise. + + * Make-lang.in (exception.o): Ok to compile with -O now. + + * decl.c (maybe_build_cleanup_1): We no longer have to unsave, as + we know it will be done later by the backend. + + * decl2.c (lang_f_options): Remove support for short temps. + * lang-options.h: Likewise. + +Wed Apr 23 04:12:06 1997 Jason Merrill + + * tree.c (varargs_function_p): New fn. + * method.c (emit_thunk): Replace broken generic code with code to + generate a heavyweight thunk function. + +Tue Apr 22 02:45:18 1997 Jason Merrill + + * pt.c (process_template_parm): pedwarn about floating-point parms. + + * decl.c (grokdeclarator): inline no longer implies static. + + * spew.c (yylex): Always return the TYPE_DECL if we got a scope. + +Mon Apr 21 15:42:27 1997 Jason Merrill + + * class.c (check_for_override): The signature of an overriding + function is not changed. + + * call.c (build_over_call): Move setting of conv into the loop. + Note: this change, along with the related changes of the 18th thru + the 20th of April, fix an infinite loop problem in conversions. + +Sun Apr 20 16:24:29 1997 Jason Merrill + + * call.c (build_user_type_conversion_1): Really ignore rvalue + conversions when looking for a REFERENCE_TYPE. + + * cvt.c (build_up_reference): Eviscerate, use build_unary_op. + * cp-tree.h (TREE_REFERENCE_EXPR): #if 0. + * typeck.c (decay_conversion): Don't set TREE_REFERENCE_EXPR. + (build_unary_op): Likewise. + * call.c (build_over_call): See through a CONVERT_EXPR around the + ADDR_EXPR for on a temporary. + * typeck.c (c_expand_return): See through a CONVERT_EXPR around + the ADDR_EXPR for a local variable. + +Fri Apr 18 12:11:33 1997 Jason Merrill + + * call.c (build_user_type_conversion_1): If we're trying to + convert to a REFERENCE_TYPE, only consider lvalue conversions. + (build_new_function_call): Print candidates. + (implicit_conversion): Try a temp binding if the lvalue conv is BAD. + (reference_binding): Binding a temporary of a reference-related type + is BAD. + +Thu Apr 17 14:37:22 1997 Brendan Kehoe + + * inc/typeinfo (type_info::before): Add cv-qualifier-seq. + * tinfo2.cc (type_info::before): Likewise. + +Mon Apr 14 12:38:17 1997 Jason Merrill + + * call.c (implicit_conversion): Oops. + +Fri Apr 11 02:18:30 1997 Jason Merrill + + * call.c (implicit_conversion): Try to find a reference conversion + before binding a const reference to a temporary. + +Wed Apr 2 12:51:36 1997 Mike Stump + + * exception.cc (__default_unexpected): Call terminate by default, + so that if the user overrides terminate, the correct function will + be called. + +Wed Mar 19 14:14:45 1997 Mike Stump + + * parse.y (left_curly): Avoid trying to use any fields of + error_mark_node, as there aren't any. + +Thu Mar 13 16:33:22 1997 Jason Merrill + + * lex.c (do_identifier): Avoid breaking on overloaded methods + as default arguments. + +Wed Mar 12 13:55:10 1997 Hans-Peter Nilsson + + * call.c (add_template_candidate): Initialize the variable "dummy". + +Mon Mar 10 15:13:14 1997 Brendan Kehoe + + * decl.c (start_decl): Make sure TYPE isn't an error_mark_node + before we try to use TYPE_SIZE and TREE_CONSTANT on it. + +Fri Mar 7 13:19:36 1997 Brendan Kehoe + + * cp-tree.h (comp_ptr_ttypes, more_specialized): Add decl. + (debug_binfo): Delete decl, not needed. + + * tree.c (fnaddr_from_vtable_entry, function_arg_chain, + promotes_to_aggr_type): Delete fns. + * cp-tree.h (FNADDR_FROM_VTABLE_ENTRY, + SET_FNADDR_FROM_VTABLE_ENTRY, FUNCTION_ARG_CHAIN, + PROMOTES_TO_AGGR_TYPE): Delete alternates to #if 1. + + * decl.c (pending_invalid_xref{,_file,_line}): Delete unused vars. + + * friend.c (is_friend_type): Delete fn. + * cp-tree.h (is_friend_type): Delete decl. + + * decl.c (original_result_rtx, double_ftype_double, + double_ftype_double_double, int_ftype_int, long_ftype_long, + float_ftype_float, ldouble_ftype_ldouble, last_dtor_insn): Make static. + * typeck.c (original_result_rtx, warn_synth): Delete extern decls. + + * decl.c (push_overloaded_decl{,_top_level}): Make static, adding + fwd decls. + * cp-tree.h (push_overloaded_decl{,_top_level}): Delete decls. + + * decl.c (pushdecl_nonclass_level): #if 0, unused. + * cp-tree.h (pushdecl_nonclass_level): #if 0 decl. + + * lex.c (reinit_lang_specific): #if 0, unused. + * cp-tree.h (reinit_lang_specific): #if 0 decl. + + * decl.c (revert_static_member_fn): Make static, adding fwd decl. + * cp-tree.h (revert_static_member_fn): Delete decl. + + * class.c (root_lang_context_p): Delete fn. + * cp-tree.h (root_lang_context_p): Delete decl. + + * decl.c (set_current_level_tags_transparency): #if 0, unused. + * cp-tree.h (set_current_level_tags_transparency): #if 0 decl. + + * lex.c (set_vardecl_interface_info): Make static. + * cp-tree.h (set_vardecl_interface_info): Delete decl. + + * call.c (find_scoped_type): Make static. + * cp-tree.h (find_scoped_type): Delete decl. + + * search.c (convert_pointer_to_vbase): Make static. + * cp-tree.h (convert_pointer_to_vbase): Delete decl. + + * decl.c (const_ptr_type_node): Likewise. + * cp-tree.h (const_ptr_type_node): Delete decl. + + * typeck.c (common_base_type): Make static. + * cp-tree.h (common_base_types): Delete erroneous decl. + + * pt.c (classtype_mangled_name): Make static. + * cp-tree.h (classtype_mangled_name): Delete decl. + + * lex.c (check_newline): Make static. + * cp-tree.h (check_newline): Delete decl. + + * typeck.c (build_x_array_ref): Delete fn, same idea as + grok_array_decl. + * cp-tree.h (build_x_array_ref): Delete decl. + + * lex.c (copy_decl_lang_specific): Delete fn, same idea as + copy_lang_decl. + * cp-tree.h (copy_decl_lang_specific): #if 0 decl. + + * class.c (build_vtable_entry): Make static. + * cp-tree.h (build_vtable_entry): Delete decl. + + * class.c (build_vbase_pointer): Make static. + * cp-tree.h (build_vbase_pointer): Delete decl. + + * sig.c (build_sptr_ref): Add forward decl and make static. + * cp-tree.h (build_sptr_ref): Delete decl. + + * call.c (build_new_method_call): Add forward decl and make static. + * cp-tree.h (build_new_method_call): Delete decl. + + * call.c (build_object_call): Make static. + * class.c (check_for_override, complete_type_p, mark_overriders): + Likewise. + * decl.c (cp_function_chain): Likewise. + * lex.c (set_typedecl_interface_info, reinit_parse_for_block): + Likewise. + * pt.c (comp_template_args, get_class_bindings, push_tinst_level): + Likewise. + * tree.c (build_cplus_array_type_1): Likewise. + * typeck.c (comp_ptr_ttypes_{const,real,reinterpret}): Likewise. + (comp_target_parms): Likewise. + + * init.c (build_builtin_call): Make static. + * cp-tree.h (build_builtin_call): Delete decl. + + * typeck.c (binary_op_error): Delete decl. + * cp-tree.h (binary_op_error): Likewise. + +Thu Mar 6 16:13:52 1997 Brendan Kehoe + + * call.c (build_method_call): Compare against error_mark_node + directly, rather than the ERROR_MARK tree code. + * cvt.c (cp_convert): Likewise. + * decl.c (print_binding_level): Likewise. + (duplicate_decls): Likewise. + (grokdeclarator): Likewise. + (grokdeclarator): Likewise. + * init.c (expand_aggr_init_1): Likewise. + (decl_constant_value): Likewise. + * method.c (build_opfncall): Likewise. + (hack_identifier): Likewise. + * typeck.c (build_modify_expr): Likewise. + + * typeck.c (build_c_cast): Don't decl TYPE as register tree. + +Sun Mar 2 02:54:36 1997 Bruno Haible + + * pt.c (unify): Strip NOP_EXPR wrappers before unifying integer values. + + * pt.c (coerce_template_parms): Add new error message. + + * method.c (build_overload_value): Implement name mangling for + floating-point template arguments. + + * method.c (build_overload_int, icat, dicat): Fix mangling of template + arguments whose absolute value doesn't fit in a signed word. + +Mon Mar 3 12:14:54 1997 Brendan Kehoe + + * friend.c: New file; put all of the friend stuff in here. + * init.c: Instead of here. + * Makefile.in (CXX_OBJS): Add friend.o. + (friend.o): Add dependencies. + * Make-lang.in (CXX_SRCS): Add $(srcdir)/cp/friend.c. + +Sun Mar 2 11:04:43 1997 Jason Merrill + + * call.c (build_scoped_method_call): Complain if the scope isn't a + base. + +Wed Feb 26 11:31:06 1997 Jason Merrill + + * parse.y (left_curly): Don't crash on erroneous type. + + * init.c (build_delete): Fix type of ref. + +Tue Feb 25 12:41:48 1997 Jason Merrill + + * search.c (get_vbase_1): Renamed from get_vbase. + (get_vbase): Wrapper, now non-static. + (convert_pointer_to_vbase): Now static. + + * call.c (build_scoped_method_call): Accept a binfo for BASETYPE. + * init.c (build_delete): Pass one. + (build_partial_cleanup_for): Use build_scoped_method_call. + * decl.c (finish_function): Pass a binfo. + +Mon Feb 24 15:00:12 1997 Jason Merrill + + * call.c (build_over_call): Only synthesize non-trivial copy ctors. + + * typeck.c (build_c_cast): Lose other reference to flag. + + * call.c (build_field_call): Don't look for [cd]tor_identifier. + * decl2.c (delete_sanity): Remove meaningless use of + LOOKUP_HAS_IN_CHARGE. + * decl.c (finish_function): Use build_scoped_method_call instead + of build_delete for running vbase dtors. + * init.c (build_delete): Call overload resolution code instead of + duplicating it badly. + +Thu Feb 20 15:12:15 1997 Jason Merrill + + * call.c (build_over_call): Call mark_used before trying to elide + the call. + + * decl.c (implicitly_declare): Don't set DECL_ARTIFICIAL. + +Wed Feb 19 11:18:53 1997 Brendan Kehoe + + * typeck.c (build_modify_expr): Always pedwarn for a cast to + non-reference used as an lvalue. + +Wed Feb 19 10:35:37 1997 Jason Merrill + + * cvt.c (cp_convert_to_pointer): Convert from 0 to a pmf properly. + +Tue Feb 18 15:40:57 1997 Jason Merrill + + * parse.y (handler): Fix template typo. + +Sun Feb 16 02:12:28 1997 Jason Merrill + + * error.c (lang_decl_name): New fn. + * tree.c (lang_printable_name): Use it. + +Fri Feb 14 16:57:05 1997 Mike Stump + + * g++spec.c: Include config.h so that we can catch bzero #defines + from the config file. + +Tue Feb 11 13:50:48 1997 Mike Stump + + * new1.cc: Include a declaration for malloc, to avoid warning, and + avoid lossing on systems that require one (ones that define malloc + in xm.h). + +Mon Feb 10 22:51:13 1997 Bruno Haible + + * decl2.c (max_tinst_depth): New variable. + (lang_decode_option): Parse "-ftemplate-depth-NN" command line + option. + * pt.c (max_tinst_depth): Variable moved. + * lang-options.h: Declare "-ftemplate-depth-NN" command line option + as legal. + +Fri Feb 7 15:43:34 1997 Jason Merrill + + * decl.c (xref_basetypes): Allow a base class that depends on + template parms to be incomplete. + + * decl2.c (build_expr_from_tree): Support typeid(type). + * rtti.c (get_typeid): Support templates. + (expand_si_desc, expand_class_desc): Fix string length. + (expand_ptr_desc, expand_attr_desc, expand_generic_desc): Likewise. + +Tue Feb 4 11:28:24 1997 Jason Merrill + + * pt.c (unify, case TEMPLATE_CONST_PARM): Use cp_tree_equal. + + * pt.c (tsubst): Put it back for -fno-ansi-overloading. + +Mon Feb 3 18:41:12 1997 Jason Merrill + + * pt.c (tsubst, case FUNCTION_DECL): Lose obsolete code that + smashes together template and non-template decls of the same + signature. + +Thu Jan 30 19:18:00 1997 Jason Merrill + + * pt.c (tsubst): Don't recurse for the type of a TYPENAME_TYPE. + +Wed Jan 29 11:40:35 1997 Brendan Kehoe + + * decl.c (duplicate_decls): Next route, pedwarn about different + exceptions if -pedantic *or* olddecl !DECL_IN_SYSTEM_HEADER. + +Tue Jan 28 20:43:29 1997 Brendan Kehoe + + * cp-tree.h (HAS_DEFAULT_IMPLEMENTATION): Delete macro. + (struct lang_type): Delete has_default_implementation member. + Increase dummy to 21. + * decl.c (start_method): Delete usage. + + * cp-tree.h (build_call, null_ptr_cst_p, in_function_p, + store_after_parms, start_decl_1, auto_function): Add decls. + (get_arglist_len_in_bytes, declare_implicit_exception, + have_exceptions_p, make_type_decl, typedecl_for_tag, + store_in_parms, pop_implicit_try_blocks, push_exception_cleanup, + build_component_type_expr, cplus_exception_name, + {make,clear}_anon_parm_name, dont_see_typename): Removed decls. + * call.c (build_this): Make static. + (is_complete): Likewise. + (implicit_conversion): Likewise. + (reference_binding): Likewise. + (standard_conversion): Likewise. + (strip_top_quals): Likewise. + (non_reference): Likewise. + (build_conv): Likewise. + (user_harshness): Likewise. + (rank_for_ideal): Likewise. + * decl.c (start_decl_1): Delete forward decl. + (push_decl_level): Make static. + (resume_binding_level): Make static. + (namespace_bindings_p): Make static. + (declare_namespace_level): Make static. + (lookup_name_real): Make static. + (duplicate_decls): Make static. Take register off NEWDECL and + OLDDECL parm decls. + * decl2.c (get_sentry): Make static. + (temp_name_p): Delete fn. + * except.c (auto_function): Delete decl. + * lex.c (handle_{cp,sysv}_pragma): Make static. + (handle_sysv_pragma) [HANDLE_SYSV_PRAGMA]: Add forward decl. + * method.c (do_build_{copy_constructor,assign_ref}): Make static. + * pt.c (tsubst_expr_values): Make static. + * rtti.c (combine_strings): Delete decl. + +Tue Jan 28 16:40:40 1997 Jason Merrill + + * pt.c (push_template_decl): Handle getting a typedef. + + * call.c (build_new_function_call): Complain about void arg. + +Tue Jan 28 15:25:09 1997 Brendan Kehoe + + * decl.c (duplicate_decls): Give pedwarn of different exceptions + if -pedantic, instead of olddecl !DECL_IN_SYSTEM_HEADER. + +Mon Jan 27 19:21:29 1997 Mike Stump + + * except.c (expand_throw): Don't expand the cleanup tree here, + since we are not going to write the rtl out. Fixes problem with + -g -O on SPARC. + +Mon Jan 27 16:24:35 1997 Sean McNeil + + * Make-lang.in: Add $(exeext) as necessary. + +Mon Jan 27 13:20:39 1997 Mike Stump + + * parse.y (handler_seq): Must have at least one catch clause. + +Sat Jan 25 12:00:05 1997 Jason Merrill + + * call.c (add_builtin_candidate): Restore ?: hack. + + * decl.c (grok_op_properties): More warnings. + +Sat Jan 25 08:50:03 1997 Brendan Kehoe + + * decl.c (duplicate_decls): On second thought, do it as a pedwarn + still but only if !DECL_IN_SYSTEM_HEADER (olddecl). + + * decl.c (duplicate_decls): Scale back to a warning, and only do + 'em if -pedantic. + +Fri Jan 24 17:52:54 1997 Mike Stump + + * decl.c (duplicate_decls): pedwarn mismatched exception + specifications. + +Thu Jan 23 18:18:54 1997 Mike Stump + + * call.c (build_new_method_call): Don't display the invisible + argument for controlling virtual bases. + +Thu Jan 23 16:48:10 1997 Mike Stump + + * new: Add nothrow new and delete, bad_alloc and throw specifications + for delete. + * decl.c (init_decl_processing): Add throw specification for delete. + * new.cc (nothrow): Define. + * lex.c (real_yylex): Removing warning that throw and friends are + keywords. + * new1.cc (operator new (size_t sz, const nothrow_t&)): Define. + * new2.cc (operator new[] (size_t sz, const nothrow_t&): Define. + * Make-lang.in: Add new{1,2}.{cc,o}. + +Thu Jan 23 16:39:06 1997 Jason Merrill + + * lex.c (cons_up_default_function): Fix return type of synth op=. + + * init.c (emit_base_init): Add warnings for uninitialized members + and bases. + + * decl.c (xref_basetypes): Add warning for non-polymorphic type + with destructor used as base type. + + * decl.c (grok_op_properties): Add warning for op= returning void. + * typeck.c (c_expand_return): Add warning for op= returning anything + other than *this. + + * class.c (finish_struct_1): Add warning for class with pointers + but not copy ctor or copy op=. + + * cp-tree.h (TI_PENDING_TEMPLATE_FLAG): New macro. + * pt.c (add_pending_template): Use it instead of LANG_FLAG_0. + (instantiate_template): If -fexternal-templates, add this + instantiation to pending_templates. + + * decl2.c (copy_assignment_arg_p): Disable old hack to support + Booch components. + +Tue Jan 21 18:32:04 1997 Mike Stump + + * cvt.c (cp_convert): pedwarn enum to pointer conversions. + +Mon Jan 20 17:59:51 1997 Jason Merrill + + * call.c (standard_conversion): Handle getting references. Tack + on RVALUE_CONV here. Do it for non-class types, too. + (reference_binding): Pass references to standard_conversion. + (implicit_conversion): Likewise. + (add_builtin_candidate): Disable one ?: kludge. + (convert_like): Handle RVALUE_CONVs for non-class types. + (joust): Disable the other ?: kludge. + +Mon Jan 20 14:53:13 1997 Brendan Kehoe + + * decl.c (init_decl_processing): Add code to build up common + function types beforehand, to avoid creation then removal of + things already in the hash table. + +Mon Jan 20 14:43:49 1997 Jason Merrill + + * decl.c (finish_function): Also zero out DECL_INCOMING_RTL for + the arguments. + + * error.c (dump_expr, TEMPLATE_CONST_PARM): Don't require + current_template_parms. + +Fri Jan 17 10:25:42 1997 Jason Merrill + + * search.c (lookup_field): Don't return a function, check want_type. + +Thu Jan 16 18:14:35 1997 Brendan Kehoe + + * init.c (build_new): Make sure PLACEMENT has a type. + +Thu Jan 16 17:40:28 1997 Jason Merrill + + * init.c (build_new): Support new (nothrow). + +Wed Jan 15 12:38:14 1997 Jason Merrill + + * pt.c (instantiate_decl): Also do push_to_top_level before setting + up DECL_INITIAL. + + * cp-tree.h (PARM_DEFAULT_FROM_TEMPLATE): New macro. + * pt.c (tsubst): Defer instantiation of default args. + * call.c (build_over_call): Until here. + +Wed Jan 15 10:08:10 1997 Brendan Kehoe + + * search.c (lookup_field): Make sure we have an + IDENTIFIER_CLASS_VALUE before we try to return it. + +Thu Jan 9 07:19:01 1997 Brendan Kehoe + + * call.c (build_method_call): Delete unused var PARM. + (build_overload_call_real): Likewise. + (build_object_call): Delete unused var P. + (build_new_op): Likewise. + * decl.c (builtin_type_tdescs_{arr, len, max}): #if 0 out static + var definitions, which are never used. + (shadow_tag): Delete unused var FN. + * expr.c (cplus_expand_expr): Delete unused var ORIGINAL_TARGET. + * init.c (build_new): Delete unused var ALLOC_TEMP. + * method.c (hack_identifier): Delete unused var CONTEXT. + (do_build_copy_constructor): Delete unused var NAME. + (synthesize_method): Delete unused var BASE. + * pt.c (lookup_template_class): Delete unused var CODE_TYPE_NODE. + * rtti.c (build_headof): Delete unused var VPTR. + (get_typeid): Delete unused var T. + * typeck.c (build_conditional_expr): Delete unused vars ORIG_OP1 + and ORIG_OP2. + (build_ptrmemfunc): Delete unused vars U and NINDEX. + * typeck2.c (build_functional_cast): Delete unused var BINFO. + +Wed Jan 8 13:09:54 1997 Jason Merrill + + * search.c (lookup_field): Use IDENTIFIER_CLASS_VALUE to look up + things in a type being defined. + * decl.c (finish_enum): Reverse the values so that they are in + the correct order. + + * pt.c (instantiate_class_template): Don't initialize + BINFO_BASETYPES until the vector is filled out. + (unify): Don't abort on conflicting bindings, just fail. + (instantiate_decl): Do push_tinst_level before any tsubsting. + + * method.c (build_overload_value): Handle getting a + TEMPLATE_CONST_PARM for a pointer. + +Tue Jan 7 14:00:58 1997 Jason Merrill + + * init.c (expand_member_init): Don't give 'not a base' error for + templates. + + * pt.c (instantiate_decl): Call import_export_decl later. + + * pt.c (instantiate_class_template): Return a value. + + * parse.y (extension): New rule for __extension__. + (extdef, unary_expr, decl, component_decl): Use it. + +Tue Jan 7 09:20:28 1997 Mike Stump + + * class.c (base_binfo): Remove unused base_has_virtual member. + (finish_base_struct): Likewise. + (finish_struct_1): Likewise. + +Tue Dec 31 20:25:50 1996 Mike Stump + + * search.c (expand_upcast_fixups): Fix bogus code generation + problem where the generated code uses the wrong index into the + runtime built vtable on the stack. Old code could clobber random + stack values. + +Tue Dec 31 15:16:56 1996 Mike Stump + + * init.c (perform_member_init): Make sure the partial EH cleanups + live on the function_obstack. + +Fri Dec 27 10:31:40 1996 Paul Eggert + + * Make-lang.in (g++spec.o): Don't use $< with an explicit target; + this isn't portable to some versions of `make' (e.g. Solaris 2.5.1). + +Tue Dec 24 10:24:03 1996 Jeffrey A Law + + * decl.c (grokvardecl): Avoid ANSI style initialization. + +Sun Dec 22 04:22:06 1996 Jason Merrill + + * pt.c (tsubst): Tweak arg types for a FUNCTION_TYPE. + +Fri Dec 20 17:09:25 1996 Jason Merrill + + * pt.c (instantiate_class_template): Call grok_{ctor,op}_properties. + +Fri Dec 20 12:17:12 1996 Brendan Kehoe + + * g++spec.c (lang_specific_driver): Put missing hyphen in front of + arguments we compare against. Start the count of I at 1, not 0, + since argv[0] is still the command. + +Thu Dec 19 11:53:57 1996 Stan Shebs + + * lang-specs.h: Accept .cp as an C++ extension. + +Mon Dec 16 22:43:31 1996 Brendan Kehoe + + * cp-tree.h (ptr_reasonably_similar): Add decl. + +Thu Dec 12 15:00:35 1996 Brendan Kehoe + + * decl.c (grokvardecl): Change SPECBITS parm to be the SPECBITS_IN + pointer. New local SPECBITS with the parm's value. + (grokdeclarator): Pass &specbits down. + + * parse.y (expr_no_commas): Make sure $$ is not an error_mark_node + before we try to do C_SET_EXP_ORIGINAL_CODE on it. + + * search.c (envelope_add_decl): Check that the CLASSTYPE_CID of + CONTEXT is not 0 before we try to use TYPE_DERIVES_FROM. + + * decl.c (cplus_expand_expr_stmt): Only expand the expr if EXP is + not an error_mark_node. + +Sat Dec 7 17:20:22 1996 Jason Merrill + + * cp-tree.h (TYPE_MAIN_DECL): Use TYPE_STUB_DECL. + * *.c: Use TYPE_MAIN_DECL instead of TYPE_NAME where appropriate. + +Fri Dec 6 14:40:09 1996 Jason Merrill + + * decl.c (grokdeclarator): When giving an anonymous struct a name, + replace TYPE_NAME instead of TYPE_IDENTIFIER (so TYPE_STUB_DECL is + not affected). + + * typeck2.c (build_m_component_ref): If component is a pointer + to data member, resolve the OFFSET_REF now. + + * call.c (convert_like): Don't go into infinite recursion. + + * pt.c (coerce_template_parms): Use tsubst_expr for non-type args. + + * class.c (finish_struct_1): Set DECL_ARTIFICIAL on the vptr. + * tree.c (layout_basetypes): And on the vbase ptr. + +Thu Dec 5 02:11:28 1996 Jason Merrill + + * decl.c (BOOL_TYPE_SIZE): Define in terms of POINTER_SIZE or + CHAR_TYPE_SIZE so bool is always the same size as another type. + + * decl.c (pushtag): Set DECL_IGNORED_P for DWARF, too. + +Tue Dec 3 23:18:37 1996 Jason Merrill + + * decl2.c (grok_x_components): Remove synthesized methods from + TYPE_METHODS of an anonymous union, complain about member + functions. + * decl.c (shadow_tag): Wipe out memory of synthesized methods in + anonymous unions. + (finish_function): Just clear the DECL_RTL of our arguments. + +Fri Nov 29 21:54:17 1996 Jason Merrill + + * decl2.c (finish_file): Emit DWARF debugging info for static data + members. + + * pt.c (tsubst): If t is a stub decl, return the stub decl for type. + +Wed Nov 27 14:47:15 1996 Bob Manson + + * typeck.c (build_component_ref): Don't die if COMPONENT isn't a + IDENTIFIER_NODE. + +Wed Nov 27 16:05:19 1996 Michael Meissner + + * Make-lang.in (g++-cross$(exeext)): Fix typo. + +Wed Nov 27 08:14:00 1996 Brendan Kehoe + + Make the g++ driver now be a standalone program, rather than one + that tries to run the gcc driver after munging up the options. + * Make-lang.in (g++.c, g++spec.o): New rules. + (g++.o): New rule, based on gcc.o with -DLANG_SPECIFIC_DRIVER + added. + (g++$(exeext)): New rule, based on xgcc rule. + (g++-cross$(exeext)): Now just copies g++$(exeext) over. + * g++spec.c: New file. + * g++.c: Removed file. + +Tue Nov 26 19:01:09 1996 Mike Stump + + * cvt.c (build_up_reference): Arrange for any temporary values + that have been keep in registers until now to be put into memory. + +Mon Nov 25 15:16:41 1996 Kaveh R. Ghazi + + * Make-lang.in (c++.stage[1234]): Depend upon stage[1-4]-start, so + that make -j3 bootstrap works better. + +Sun Nov 24 02:09:39 1996 Jason Merrill + + * decl.c (pushtag): Do pushdecl for anon tags. + +Thu Nov 21 16:30:24 1996 Jason Merrill + + * typeck.c (c_expand_return): Fix logic. + (unary_complex_lvalue): Avoid unused warning on address of INIT_EXPR. + +Wed Nov 20 18:47:31 1996 Bob Manson + + * g++.c (main): Make sure arglist has a final NULL entry. Add + PEXECUTE_LAST to the flags passed to pexecute, as otherwise + stdin/stdout of the invoked program are redirected to + nowheresville. + +Tue Nov 19 16:12:44 1996 Jason Merrill + + * decl.c (implicitly_declare): Set DECL_ARTIFICIAL. + +Tue Nov 19 15:48:19 1996 Mike Stump + + * init.c (resolve_offset_ref): Handle obj.vfn better. + * typeck.c (build_component_ref): Set TREE_TYPE on result from + build_vfn_ref. + +Tue Nov 19 13:14:33 1996 Mike Stump + + * typeck.c (convert_for_assignment): Also handle anachronistic + implicit conversions from (::*)() to cv void*. + * cvt.c (cp_convert_to_pointer): Likewise. + +Mon Nov 18 17:05:26 1996 Jason Merrill + + * lex.c (handle_cp_pragma): Fix bogus warning. + +Mon Nov 18 16:10:43 1996 Mike Stump + + * cvt.c (cp_convert_to_pointer): Avoid thinking a POINTER_TYPE + (METHOD_TYPE) is a TYPE_PTRMEMFUNC_P. + +Thu Nov 14 23:18:17 1996 Jason Merrill + + * class.c (finish_struct_1): Support DWARF2_DEBUG. + * search.c (dfs_debug_mark): Likewise. + * decl2.c (finish_vtable_vardecl): Likewise. + * decl.c (pushtag, finish_enum): Likewise. + * lex.c (check_newline): Use debug_* instead of calling *out + functions directly. + +Thu Nov 14 15:21:46 1996 Brendan Kehoe + + * Make-lang.in (cplib2.ready): Add else clause to avoid problems + on some picky hosts. + +Wed Nov 13 12:32:07 1996 Jason Merrill + + * class.c (finish_struct_1): A class has a non-trivial copy + constructor if it has virtual functions. + + * cvt.c (cp_convert): Always call a constructor. + + * call.c (reference_binding): Still tack on a REF_BIND + for bad conversions. + (build_user_type_conversion_1): Propagate ICS_BAD_FLAG. + + * typeck.c (convert_arguments): Pass LOOKUP_ONLYCONVERTING. + (c_expand_return): Likewise. + * typeck2.c (digest_init): Likewise for { }. + * init.c (expand_aggr_init_1): Keep the CONSTRUCTOR handling. + * cvt.c (cp_convert): Handle failure better. + +Wed Nov 13 11:51:20 1996 Brendan Kehoe + + * g++.c (main): Also set PEXECUTE_SEARCH, to make the invocation + of GCC be path-relative. + +Wed Nov 13 11:27:16 1996 Michael Meissner + + * Make-lang.in (g++-cross): G++-cross doesn't need version.o, but + it does need choose-temp.o and pexecute.o. + +Wed Nov 13 07:53:38 1996 Brendan Kehoe + + * g++.c (error) [!HAVE_VPRINTF]: Put error back for the only time + that we still use it. + (P_tmpdir, R_OK, W_OK, X_OK) [__MSDOS__]: Delete unnecessary macros. + +Wed Nov 13 02:00:26 1996 Jason Merrill + + * init.c (expand_default_init): Avoid calling constructors to + initialize reference temps. + + * cvt.c (convert_to_reference): Fix. + +Tue Nov 12 19:10:07 1996 Jason Merrill + + * cvt.c (cp_convert): Simplify for flag_ansi_overloading. + (convert_to_reference): Likewise. + * typeck.c (convert_for_initialization): Likewise. + * init.c (expand_default_init): Likewise. + (expand_aggr_init_1): Likewise. + * cp-tree.h (CONV_NONCONVERTING): Lose. + * typeck.c (build_c_cast): Lose allow_nonconverting parm. + * *.c: Adjust. + * call.c (build_user_type_conversion_1): Assume LOOKUP_ONLYCONVERTING. + +Tue Nov 12 16:29:04 1996 Brendan Kehoe + + * pt.c (tsubst_expr): Reverse args to expand_start_catch_block. + +Tue Nov 12 15:26:17 1996 Jason Merrill + + * init.c (expand_aggr_init_1): Don't crash on non-constructor + TARGET_EXPR. + +Tue Nov 12 14:00:50 1996 Brendan Kehoe + + * g++.c: Include gansidecl.h. + (VPROTO, PVPROTO, VA_START): Delete. + (choose_temp_base_try, choose_temp_base, perror_exec, + run_dos) [__MSDOS__]: Delete fns. + (pfatal_with_name): Delete fn. + (temp_filename): Declare like in gcc.c. + (pexecute, pwait, choose_temp_base): Declare from gcc.c. + (error_count, signal_count): Define. + (error): Delete both definitions. + (PEXECUTE_{FIRST,LAST,SEARCH,VERBOSE}): Define from gcc.c. + (pfatal_pexecute): Add fn from gcc.c. + (main): Rename local VERBOSE var to VERBOSE_FLAG. Rewrite the + code to use the pexecute stuff also used by gcc.c. + (MIN_FATAL_STATUS): Define. + * Make-lang.in (g++): Add dependency on and linking with + choose-temp.o and pexecute.o. + + * cp-tree.h: Include gansidecl.h. + (STDIO_PROTO): Delete #undef/#define. + * cvt.c (NULL): Delete #undef/#define. + * expr.c (NULL): Likewise. + * init.c (NULL): Likewise. + * rtti.c (NULL): Likewise. + * xref.c (NULL): Likewise. + + * cp-tree.h (build_user_type_conversion): Add prototype. + * call.c (build_user_type_conversion): Delete prototype. Correct + decl of FLAGS arg to be an int. + * cvt.c (build_user_type_conversion): Likewise. + +Tue Nov 12 12:16:20 1996 Jason Merrill + + * cp-tree.def: Add TRY_BLOCK and HANDLER. + * except.c (expand_start_catch_block): Support templates. + * parse.y (try_block, handler_seq): Likewise. + * pt.c (tsubst_expr): Support TRY_BLOCK and HANDLER. + +Mon Nov 11 13:57:31 1996 Jason Merrill + + * pt.c (current_template_args): New fn. + (push_template_decl): Use it. + * decl.c (grokdeclarator): Use it. + + * decl2.c (build_expr_from_tree): Dereference ref vars. + + * decl.c (grokdeclarator): Generalize handling of TYPENAME_TYPEs in + the decl-specifier-seq. + + * decl.c (grok_op_properties): Don't force the type of a conversion + op to be complete. Don't warn about converting to the same type + for template instantiations. + + * decl2.c (finish_file): Don't call instantiate_decl on synthesized + methods. + +Mon Nov 11 13:20:34 1996 Bob Manson + + * typeck.c (get_delta_difference): Remove previous bogusness. + Don't give errors if force is set. + +Fri Nov 8 17:38:44 1996 Jason Merrill + + * decl2.c (finish_file): Don't emit debug info. + * decl.c (pushdecl): Lose obsolete code. + (grokdeclarator): Still do the long long thing after complaining. + * search.c (note_debug_info_needed): Don't do anything if we're in a + template. + * method.c (synthesize_method): For non-local classes, + push_to_top_level first. + +Fri Nov 8 11:52:28 1996 Bob Manson + + * typeck.c (get_delta_difference): Add no_error parameter. + (build_ptrmemfunc): Call get_delta_difference with no_error set; + we don't want error messages when converting unrelated + pointer-to-member functions. + +Thu Nov 7 11:16:24 1996 Mike Stump + + * error.c (dump_expr): Improve the wording on error messages that + involve pointer to member functions. + +Tue Nov 5 17:12:05 1996 Mike Stump + + * cvt.c (cp_convert_to_pointer): Move code for conversions from + (::*)() to void* or (*)() up a bit, so that we can convert from + METHOD_TYPEs as well. + +Tue Nov 5 14:54:17 1996 Jason Merrill + + * rtti.c (get_tinfo_fn): Make sure 'type' is permanent. + There are no 'member' types. + (get_tinfo_fn_dynamic): Diagnose typeid of overloaded fn. + (build_x_typeid): Handle errors. + +Mon Nov 4 17:43:12 1996 Mike Stump + + * typeck.c (convert_for_assignment): Handle anachronistic implicit + conversions from (::*)() to void* or (*)(). + * cvt.c (cp_convert_to_pointer): Likewise. + (cp_convert_to_pointer_force): Remove cp_convert_to_pointer + conversions from here. + * decl2.c (lang_decode_option): Add -W{no-,}pmf-conversions. + * lang-options.h: Likewise. + * decl2.c (warn_pmf2ptr): Define. + * cp-tree.h: Declare it. + * typeck2.c (digest_init): Allow pmfs down into + convert_for_initialization. + +Sun Nov 3 09:43:00 1996 Jason Merrill + + * typeck.c (c_expand_return): Fix for returning overloaded fn. + +Fri Nov 1 08:53:17 1996 Jason Merrill + + * cp-tree.h (DIRECT_BIND): Change from INDIRECT_BIND. + * decl.c (grok_reference_init): Pass DIRECT_BIND. + * cvt.c (build_up_reference): Don't mark 'this' addressable. Use + DIRECT_BIND. + * call.c (convert_like): Don't pass INDIRECT_BIND. + * typeck.c (convert_arguments): Likewise. + * typeck.c (mark_addressable): Allow &this if flag_this_is_variable. + +Thu Oct 31 17:08:49 1996 Jason Merrill + + * typeck.c (mark_addressable): Support TARGET_EXPR, unify with + similar code in build_up_ref. + * cvt.c (build_up_reference): Drastically simplify. + +Mon Oct 28 12:45:05 1996 Jeffrey A Law + + * typeck.c (signed_or_unsigned_type): If the given type already + as the correct signedness, then just return it. + + * typeck.c ({un,}signed_type): If can't do anything, call + signed_or_unsigned_type. + +Thu Oct 24 14:21:59 1996 Bob Manson + + * decl2.c (copy_assignment_arg_p): Don't buy the farm if + current_class_type is NULL. + +Wed Oct 23 00:43:10 1996 Jason Merrill + + * class.c (finish_struct_1): Avoid empty structs by adding a field + so layout_type gets the mode right. + + * typeck.c (c_expand_return): Drastically simplify. + +Mon Oct 21 22:34:02 1996 Jason Merrill + + * typeck.c (decay_conversion): Handle overloaded methods. + +Fri Oct 18 16:03:48 1996 Jason Merrill + + * call.c (build_over_call): A TARGET_EXPR has side-effects. + +Thu Oct 17 11:31:59 1996 Mike Stump + + * cvt.c (convert_to_pointer_force): Add code to support pointer to + member function to pointer to function conversions. + * init.c (resolve_offset_ref): Add code to allow faked up objects, + ignoring them if they are not used, and giving an error, if they + are needed. + * typeck.c (get_member_function_from_ptrfunc): Fold e1 to improve + code, and so that we can give an error, if we needed an object, + and one was not provided. + (build_c_cast): Don't call default_conversion when we want to + convert to pointer to function from a METHOD_TYPE. + +Mon Oct 14 00:28:51 1996 Jason Merrill + + * Make-lang.in (cplib2.ready): Fix logic. + + * decl.c (shadow_tag): Only complain about non-artificial function + members. + + * class.c (finish_struct_1): Add synthesized methods to TYPE_METHODS. + +Fri Oct 11 16:12:40 1996 Jason Merrill + + * expr.c (cplus_expand_expr): Pre-tweak call_target like + expand_inline_function would. + + * pt.c (mark_decl_instantiated): If extern_p, call + mark_inline_for_output. + +Thu Oct 10 15:58:08 1996 Mike Stump + + * typeck.c (unary_complex_lvalue): Add code to handle intermediate + pmd conversions. + + * typeck.c (get_delta_difference): Fix wording, as we can be used + for pointer to data members. + +Tue Oct 8 12:43:51 1996 Bob Manson + + * pt.c (tsubst): If the function decl isn't a member of this + template, return a copy of the decl (including copying the + lang-specific part) so we don't hose ourselves later. + +Thu Oct 3 16:24:28 1996 Jason Merrill + + * class.c (finish_struct): Remove DWARF-specific tag handling. + * decl.c (pushtag): Likewise. + (finish_function): Always clear DECL_ARGUMENTS on function decls with + no saved RTX. + * decl2.c (finish_file): Emit DWARF debugging info for static data + members. + +Wed Oct 2 21:58:01 1996 Bob Manson + + * decl.c (duplicate_decls): Make sure the old DECL_LANG_SPECIFIC + isn't the same as the new one before we whack it. + +Mon Sep 30 13:38:24 1996 Jason Merrill + + * class.c, cp-tree.h, cvt.c, decl.c, decl2.c, gxx.gperf, hash.h, + lex.c, method.c, parse.y, typeck.c, typeck2.c: Remove + warn_traditional and warn_strict_prototypes; remove ancient + 'overload' code; remove references to flag_traditional. + +Mon Sep 30 12:58:40 1996 Mike Stump + + * input.c (sub_getch): Handle 8-bit characters in string literals. + +Sun Sep 29 03:12:01 1996 Jason Merrill + + * tree.c (mapcar): Handle CONSTRUCTORs. + (copy_to_permanent): Handle expression_obstack properly. + + * Make-lang.in (cplib2.txt): Also depend on the headers. + + * rtti.c (get_tinfo_var): Don't assume that POINTER_SIZE == + INT_TYPE_SIZE. + (expand_class_desc): Use USItype for offset field. + * tinfo.h (struct __class_type_info): Likewise. + + * method.c (build_overload_int): TYPE_PRECISION should be applied + to types. + +Sat Sep 28 14:44:50 1996 Jason Merrill + + * call.c (build_new_op): A COND_EXPR involving void must be a + builtin. + +Fri Sep 27 16:40:30 1996 Jason Merrill + + * typeck.c (build_x_component_ref): New fn. + (build_object_ref): Use it. + * parse.y (primary): Use it. + * decl2.c (build_expr_from_tree): Use it. + * cp-tree.h: Declare it. + + * decl.c (start_decl): Variable-sized arrays cannot be initialized. + * error.c (dump_type_suffix): Handle variable arrays. + +Fri Sep 27 13:14:05 1996 Brendan Kehoe + + * Make-lang.in (exception.o): Put back compiling it with -fPIC. + +Fri Sep 27 03:00:09 1996 Jason Merrill + + * decl.c (lookup_name_real): Don't try to look up anything in a + TYPENAME_TYPE. + + * tinfo2.cc (__throw_type_match_rtti): Oops. + +Thu Sep 26 22:11:05 1996 Brendan Kehoe + + * Make-lang.in (exception.o): Use -fno-PIC for now. + +Thu Sep 26 10:59:00 1996 Jason Merrill + + * rtti.c (build_dynamic_cast): Pass tinfo fns rather than + calling them. + (get_tinfo_fn_dynamic): Extracted from build_typeid. + * tinfo2.cc (__dynamic_cast): Adjust. + + * rtti.c (build_typeid): Use resolves_to_fixed_type_p. + (build_x_typeid): Likewise. + + * parse.y: Call build_x_typeid instead of build_typeid. + * cp-tree.def: Add TYPEID_EXPR. + * pt.c (tsubst_copy): Handle typeid. + * decl2.c (build_expr_from_tree): Likewise. + * rtti.c (build_x_typeid): Throw bad_typeid from here. + (build_typeid): Not here. + * cp-tree.h: Declare build_x_typeid. + +Wed Sep 25 17:26:16 1996 Jason Merrill + + * call.c (convert_like): Pull out constant values. + + * tree.c (mapcar): Use build_cplus_array_type, not build_array_type. + +Wed Sep 25 17:28:53 1996 Michael Meissner + + * decl.c (init_decl_processing): Create short int types before + creating size_t in case a machine description needs to use + unsigned short for size_t. + +Tue Sep 24 18:18:44 1996 Jason Merrill + + * Make-lang.in (exception.o): Turn off pic. + + * tinfo2.cc (__throw_type_match_rtti): Fix cv-variants of the same + type, multi-level ptr conversions. + + * rtti.c (call_void_fn): Renamed and genericized from throw_bad_cast. + (throw_bad_cast): Use it. + (throw_bad_typeid): New fn. + (build_typeid): Throw bad_typeid as needed. + Use build_call. + (synthesize_tinfo_fn): Handle functions and arrays before checking + for cv-quals. + + * Remove .h from standard C++ headers, add new.h, move into inc + subdirectory. + + * exception*: Remove pointer from object, constructors. Add + default exception::what that uses type_info::name. Add + __throw_bad_typeid. + + * init.c (build_new): Don't add a cookie to new (void *) T[2]. + +Mon Sep 23 15:21:53 1996 Jason Merrill + + * Make-lang.in: Building C++ code depends on cc1plus. + +Mon Sep 23 12:38:40 1996 Brendan Kehoe + + * decl.c (struct saved_scope): Declare PROCESSING_TEMPLATE_DECL as + a HOST_WIDE_INT, not a tree. + +Mon Sep 23 12:36:02 1996 Jason Merrill + + * exception.cc: Don't include . + + * Make-lang.in (c++.clean): Remove cplib2.*. + +Mon Sep 23 09:42:19 1996 Doug Evans + + * parse.y (component_decl_1, component_costructor_declarator case): + Pass attributes/prefix_attributes in tree list. + +Mon Sep 23 01:18:50 1996 Jason Merrill + + * tinfo{,2}.cc: #include instead of . + +Sun Sep 22 05:31:22 1996 Jason Merrill + + * lex.c (do_identifier): Don't do deferred lookup in a template + header. + + * typeck2.c (store_init_value): Oops. + + * new.{h,cc}, exception.{h,cc}, typeinfo.h, tinfo{2.cc,.cc,.h}: + New files for C++ lang-support library. + * Make-lang.in (CXX_EXTRA_HEADERS): Define. + (CXX_LIB2FUNCS): Define. + And rules for building the C++ lang-support code. + * config-lang.in (headers): Define. + (lib2funcs): Define. + +Sat Sep 21 19:17:28 1996 Jason Merrill + + * decl2.c (build_expr_from_tree): If CONSTRUCTOR has a type, call + digest_init. + * pt.c (tsubst_copy): Compute type for CONSTRUCTOR. + * typeck2.c (store_init_value): Check for initializing pmf with { } + here. + (process_init_constructor): Not here. + +Thu Sep 19 16:41:07 1996 Jason Merrill + + * pt.c (begin_template_parm_list): Increment + processing_template_decl here. + (end_template_parm_list): Not here. + (process_template_parm): No need to add 1 to it now. + * *.c: Use processing_template_decl instead of current_template_parms + to check for being in a template. + + * pt.c (uses_template_parms): Handle SCOPE_REF. Fix CONSTRUCTOR. + (tsubst_copy): Handle CONSTRUCTOR. + (instantiate_decl): Set up context properly for variables. + * decl2.c (build_expr_from_tree): Handle CONSTRUCTOR. + * class.c (finish_struct): Reverse CLASSTYPE_TAGS. + +Wed Sep 18 13:30:20 1996 Brendan Kehoe + + * lex.c (enum tree_node_kind) [GATHER_STATISTICS]: Put the enum back. + +Wed Sep 18 04:24:07 1996 Jason Merrill + + * method.c (make_thunk): Call comdat_linkage before setting the + TREE_CODE. + + * decl2.c (comdat_linkage): Use make_decl_one_only. + (import_export_decl): Likewise. + * decl.c (init_decl_processing): Check supports_one_only instead of + SUPPORTS_WEAK. + +Sat Sep 14 08:34:41 1996 Jason Merrill + + * decl2.c (grokfield): Tighten checking for access decls. + + * decl.c (make_typename_type): Resolve references to + current_class_type. Set CLASSTYPE_GOT_SEMICOLON. + (lookup_name_real): Types that depend on a template parameter get + an implicit 'typename' unless they're in the current scope. + (start_decl_1): We don't care about incomplete types that depend + on a template parm. + (grokdeclarator): Resolve 'typename's in the type specifier that + refer to members of the current scope. + + * call.c (build_over_call): Remove 'inline called before + definition' diagnostic. + (build_method_call): Likewise. + * decl.c (duplicate_decls): Downgrade 'used before declared + inline' to a warning, only with -Winline. + +Fri Sep 13 17:31:40 1996 Stan Shebs + + * mpw-make.sed: Fix include paths, add @DASH_C_FLAG@ to compile. + +Wed Sep 11 22:38:13 1996 Gerald Baumgartner + + * call.c (build_method_call): When calling a signature + default implementation, as in other cases, let instance_ptr simply + be instance. + +Wed Sep 11 22:14:44 1996 Mike Stump + + * parse.y (simple_stmt): Cleanup and use do_poplevel (). + +Wed Sep 11 22:10:48 1996 Mike Stump + + * except.c (expand_start_catch_block): Add a pushlevel so that -g + works on hppa and SPARC. + +Wed Sep 11 10:18:06 1996 Brendan Kehoe + + * typeck.c (build_indirect_ref): Catch PTR being an error_mark_node. + +Mon Sep 9 19:51:14 1996 Gerald Baumgartner + + * call.c (build_over_call): Check first whether DECL_CONTEXT exists + before testing whether it's a signature. + +Sun Sep 8 16:06:57 1996 Gerald Baumgartner + + * call.c (build_new_method_call): Don't complain about signature + pointers and references not being an aggr type. + (build_this): If a signature pointer or reference was passed in, + just return it. + (build_new_method_call): If instance is a signature pointer, set + basetype to the signature type of instance. + * sig.c (build_signature_method_call): Deleted basetype and + instance parameters, they can be found as the DECL_CONTEXT of + function and as the first argument passed in. + * cp-tree.h: Changed declaration of build_signature_method_call. + * call.c (build_method_call): Deleted first two arguments in call + of build_signature_method_call. + (build_over_call): Added call to build_signature_method_call. + +Thu Sep 5 16:51:28 1996 Jason Merrill + + * typeck.c (build_c_cast): Don't tack a non_lvalue_expr onto a + target_expr. + +Thu Sep 5 10:05:38 1996 Brendan Kehoe + + * cvt.c (convert_to_reference): Use %#T, not %#D, for error. + +Wed Sep 4 17:16:09 1996 Bob Manson + + * except.c (expand_start_try_stmts): Move to except.c in the backend. + (expand_end_try_stmts): Remove. + + * init.c (perform_member_init): Use add_partial_entry () instead + of directly manipulating lists. + (emit_base_init): Likewise. + +Wed Sep 4 12:14:36 1996 Mike Stump + + * except.c (expand_exception_blocks): Always make sure USE and + CLOBBER insns that came at the end still do, the backend relies + upon this. + +Wed Sep 4 07:44:48 1996 Jason Merrill + + * call.c (build_over_call): We can only use a TARGET_EXPR of the + right type. + +Tue Sep 3 19:26:05 1996 Jason Merrill + + * cvt.c (convert_to_reference): Revert last change, don't complain + about temp without target decl. + +Tue Sep 3 10:22:56 1996 Mike Stump + + * decl.c (grokdeclarator): Don't core dump when void() is given. + +Tue Sep 3 02:38:56 1996 Jason Merrill + + * decl.c (copy_args_p): Don't crash. + +Fri Aug 30 14:26:57 1996 Mike Stump + + * pt.c (tsubst): And support template args inside the exception + specification. + + * pt.c (tsubst): Add support for exception specifications in + template functions. + +Fri Aug 30 10:01:55 1996 Mike Stump + + * cp-tree.def (DECL_STMT): Eliminate the throw spec field, only 3 + fields now. + * cp-tree.h (start_decl): Eliminate the throw spec parameter. + (start_function): Likewise. + (start_method): Likewise. + (grokfield): Likewise. + (make_call_declarator): Add throw spec parameter. + (set_quals_and_spec): Add routine. + * lex.c (set_quals_and_spec): Likewise. + * decl.h (grokdeclarator): Eliminate the throw spec parameter. + * decl.c (shadow_tag): Eliminate the throw spec parameter to + grokdeclarator. + (groktypename): Likewise. + (start_decl): Eliminate the throw spec parameter. Eliminate the + throw spec parameter to grokdeclarator. Eliminate the throw spec + field in DECL_STMT. + (cp_finish_decl): Eliminate the throw spec field in DECL_STMT. + (grokfndecl): Remove useless set of raises. + (grokdeclarator): Eliminate the throw spec parameter. Eliminate + the throw spec parameter to start_decl. Pull the throw spec out + of the call declarator. + (grokparms): Eliminate the throw spec parameter to grokdeclarator. + (start_function): Eliminate the throw spec parameter. Eliminate + the throw spec parameter to grokdeclarator. + (start_method): Likewise. + * decl2.c (grokfield): Likewise. + (grokbitfield): Eliminate the throw spec parameter to grokdeclarator. + (grokoptypename): Likewise. + (finish_file): Eliminate the throw spec parameter to + start_function. Add throw spec to make_call_declarator. + * except.c (init_exception_processing): Add throw spec to + make_call_declarator. Eliminate the throw spec parameter to + start_decl. + (expand_start_catch_block): Eliminate the throw spec parameter to + grokdeclarator. + (expand_builtin_throw): Add throw spec to make_call_declarator. + Eliminate the throw spec parameter to start_function. + (start_anon_func): Likewise. + * lex.c (make_call_declarator): Add throw spec parameter. + (set_quals_and_spec): New routine. + (cons_up_default_function): Add throw spec to make_call_declarator. + Eliminate the throw spec parameter to grokfield. + * method.c (synthesize_method): Eliminate the throw spec parameter + to start_function. + * pt.c (process_template_parm): Eliminate the throw spec parameter + to grokdeclarator. + (tsubst): Add throw spec to make_call_declarator. + (tsubst_expr): Eliminate the throw spec parameter to start_decl. + (do_function_instantiation): Eliminate the throw spec parameter to + grokdeclarator. Eliminate the throw spec parameter to + start_function. + * rtti.c (synthesize_tinfo_fn): Eliminate the throw spec parameter + to start_function. + * parse.y (datadef): Remove non-winning optimization. + (decl): Likewise. + (fndef): Remove ambiguous error productions uncovered by grammar + fixing. + (constructor_declarator): Add exception_specification_opt here. + (component_constructor_declarator): Likewise. + (direct_after_type_declarator): Likewise. + (complex_direct_notype_declarator): Likewise. + (direct_abstract_declarator): Likewise. + (fn.def1): Remove exception_specification_opt. + (fn.def2): Likewise. + (condition): Likewise. + (initdcl0): Likewise. + (initdcl): Likewise. + (notype_initdcl0): Likewise. + (nomods_initdcl0): Likewise. + (component_decl_1): Likewise. + (component_declarator): Likewise. + (after_type_component_declarator0): Likewise. + (after_type_component_declarator): Likewise. + (notype_component_declarator): Likewise. + +Wed Aug 28 01:40:30 1996 Jason Merrill + + * call.c (build_over_call): Also use an INIT_EXPR when + initializing anything from an rvalue. + + * call.c (build_over_call): Call stabilize_reference when building + an INIT_EXPR instead of calling the copy ctor. + + * call.c (joust): Extend the previous change to all comparisons. + + * decl2.c, method.c, lex.c: Use MAKE_DECL_ONE_ONLY and + NO_LINKAGE_HEURISTICS. + + * decl2.c (finish_file): Emit any statics that weren't already. + + * typeck.c (build_static_cast): Implement. + * tree.c (build_cplus_new): Handle getting a TARGET_EXPR. + * decl.c (grokparms): Use can_convert_arg instead of + implicit_conversion directly. + (copy_args_p): New fn. + * cvt.c (convert_to_reference): Don't complain about temp with + static_cast. + (build_up_reference): Handle TARGET_EXPRs. + * call.c (build_over_call): Elide unnecessary temps. + (can_convert*): Use new overloading code. + +Tue Aug 27 13:12:21 1996 Jason Merrill + + * call.c: Move TYPE_PTR*_MACROS ... + * cp-tree.h: To here. + * typeck.c (build_reinterpret_cast): Implement. + + * call.c (add_builtin_candidate): Use TYPE_PTROB_P instead of + ptr_complete_ob. + (joust): If we're comparing a function to a builtin and the worst + conversion for the builtin is worse than the worst conversion for the + function, take the function. + + * typeck.c (build_const_cast): Implement. + (comp_ptr_ttypes_const): Like comp_ptr_ttypes, for const_cast. + (comp_ptr_ttypes_reinterpret): Like cpt, for reinterpret_cast. + +Tue Aug 27 13:14:58 1996 Bob Manson + + * rtti.c (build_dynamic_cast): Don't try to dereference exprtype + too early. Make sure we explode if exprtype turns out to be a + NULL_TREE when it shouldn't be. + +Tue Aug 27 10:56:21 1996 Mike Stump + + * cp-tree.h: New routine make_call_declarator. + * lex.c (make_call_declarator): Define it. + * except.c (init_exception_processing): Use it. + (expand_builtin_throw): Likewise. + (start_anon_func): Likewise. + * decl2.c (finish_file): Likewise. + * lex.c (cons_up_default_function): Likewise. + * parse.y: Likewise. + * pt.c (tsubst): Likewise. + +Mon Aug 26 17:40:03 1996 Mike Stump + + * decl2.c (groktypefield): Remove unused code. + +Mon Aug 26 17:00:33 1996 Mike Stump + + * gxx.gperf: Change TYPE_QUAL into CV_QUALIFIER. + * parse.y: Likewise. Change maybe_type_qual into maybe_cv_qualifier. + Change type_quals into cv_qualifiers. Change nonempty_type_quals into + nonempty_cv_qualifiers. + * hash.h: Rebuild. + + * lex.c (make_pointer_declarator): Change type_quals into + cv_qualifiers. + (make_reference_declarator): Likewise. + +Thu Aug 22 01:09:22 1996 Jason Merrill + + * decl.c (start_function): Only check interface_* for templates + with flag_alt_external_templates. + + * call.c (build_new_op): Check for comparison of different enum types. + (build_over_call): Fix arg # output. + + * typeck.c (build_component_ref): Handle pre-found TYPE_DECL. + +Wed Aug 21 00:13:15 1996 Jason Merrill + + * call.c (build_new_op): Check for erroneous args. + + * call.c (build_new_method_call): Add missing args to cp_error. + + * tree.c (error_type): Don't print reference-to-array. + + * typeck.c (convert_for_assignment): Don't say contravariance for + removing const. + +Tue Aug 20 13:23:00 1996 Jason Merrill + + * call.c (build_over_call): Diagnose bad convs for `this'. + + * lex.c (cons_up_default_function): Set DECL_ARTIFICIAL + on _ctor_arg. + + * call.c (convert_like): Handle bad convs. + (build_over_call): Handle bad convs better. + + * decl2.c: -fansi-overloading is now the default. + + * call.c (build_new_method_call): Check for erroneous args. + + * pt.c (instantiate_class_template): Propagate + TYPE_USES_MULTIPLE_INHERITANCE. + +Tue Aug 20 13:09:57 1996 Mike Stump + + * call.c (enforce_access): Add static to routine. + +Sun Aug 18 14:35:54 1996 Jason Merrill + + * call.c (build_user_type_conversion_1): Fix bad handling. + (compare_ics): Likewise. + +Sat Aug 17 21:54:11 1996 Jason Merrill + + * call.c (standard_conversion): Oops. + +Sat Aug 17 16:28:11 1996 Geoffrey Noer + + * g++.c: Update test for win32 (&& ! cygwin32). + +Sat Aug 17 03:45:31 1996 Jason Merrill + + * typeck.c (comp_ptr_ttypes_real): Handle OFFSET_TYPEs properly. + (ptr_reasonably_similar): New fn. + * call.c (BAD_RANK): New rank. + (ICS_BAD_FLAG): New macro. + (standard_conversion): Handle almost-right pointer conversions. + (reference_binding): Handle bad rvalue bindings. + (add_*_candidate): Stuff. + (build_over_call): Pass bad conversions to convert_for_initialization. + (compare_ics): Handle bad convs. + (joust): Likewise. + +Fri Aug 16 15:02:19 1996 Bob Manson + + * init.c (expand_vec_init): Use ptrdiff_type_node instead of + integer_type_node when computing pointer offsets. + +Fri Aug 16 01:28:32 1996 Jason Merrill + + * tree.c (lvalue_type): New fn. + (error_type): New fn. + * call.c (op_error): Use error_type. + (add_conv_candidate): Use lvalue_type. + (add_builtin_candidates): Likewise. + * error.c (args_as_string): Use error_type. + +Thu Aug 15 17:27:13 1996 Jason Merrill + + * pt.c (instantiate_decl): Evaluate DECL_INITIAL of a VAR_DECL here. + (tsubst): Not here. + + * decl.c (init_decl_processing): With -ansi, __null's type is the + signed integral type with the same number of bits as a pointer. + Introduce a new variable null_node for it. + * cp-tree.h: Adjust. + * call.c (null_ptr_cst_p): Adjust. + +Thu Aug 15 17:09:54 1996 Mike Stump + + * except.c (do_unwind): Mark %i7 as used on the SPARC so we can + optimize. + +Thu Aug 15 01:36:49 1996 Jason Merrill + + * decl2.c (import_export_decl): Ignore #pragma interface for tinfo + fns of classes without virtual functions. + + * call.c (add_function_candidate): Handle `this' specially. + (compare_ics): Likewise. + +Tue Aug 13 12:16:10 1996 Jason Merrill + + * typeck.c (build_conditional_expr): Fix handling of __null. + + * decl2.c (comdat_linkage): New fn. + (import_export_vtable): Use it. + (import_export_decl): Use it. + * method.c (make_thunk): Use it. + +Mon Aug 12 00:09:18 1996 Jason Merrill + + * pt.c (end_template_decl): If we don't actually have parms, return. + * parse.y (template_header): Accept 'template <>'. + + * errfn.c: Allow 5 args. + +Sun Aug 11 15:20:58 1996 Jason Merrill + + * tree.c (make_temp_vec): New fn. + * pt.c (push_template_decl): Handle partial specs. + (instantiate_class_template): Likewise. + (more_specialized): Use get_bindings. + (more_specialized_class): New fn. + (get_class_bindings): New fn. + (most_specialized_class): New fn. + (do_function_instantiation): List candidates for ambiguous case. + * decl.c (duplicate_decls): Lose reference to DECL_TEMPLATE_MEMBERS. + (shadow_tag): Call push_template_decl for partial specializations. + * parse.y: Likewise. + * cp-tree.h (DECL_TEMPLATE_SPECIALIZATIONS): Replaces + DECL_TEMPLATE_MEMBERS. + * call.c (print_z_candidates): Reduce duplication. + +Fri Aug 9 14:36:08 1996 Jason Merrill + + * decl2.c (lang_decode_option): Allow -fansi-overloading. + +Thu Aug 8 17:04:18 1996 Jason Merrill + + * pt.c (get_bindings): New fn. + (most_specialized): Likewise. + (do_function_instantiation): Use them. + (add_maybe_template): New fn. + * cp-tree.h (DECL_MAYBE_TEMPLATE): New macro. + * call.c (build_new_op): Handle guiding decls. + (build_new_function_call): Likewise. + * decl2.c (finish_file): Likewise. + + * decl2.c (mark_used): Do synthesis here. + * call.c (build_method_call): Not here. + (build_over_call): Or here. + * typeck.c (build_function_call_real): Or here. + * tree.c (bot_manip): Call mark_used on functions used in default + args. + +Thu Aug 8 17:48:16 1996 Michael Meissner + + * decl2.c (import_export_vtable): Delete code that disabled vtable + heuristic on systems with ASM_OUTPUT_EXTERNAL. + +Wed Aug 7 12:44:11 1996 Jason Merrill + + * typeck.c (build_x_function_call): Handle static call context + better. + + * decl.c (finish_function): Set the DECL_CONTEXT of the result to + the function, not its outer block. + + * call.c (build_field_call): Pass fields on to build_opfncall + regardless of TYPE_OVERLOADS_CALL_EXPR. + (build_method_call): Pass on to build_new_method_call sooner. + + * typeck.c (build_ptrmemfunc): Just return what instantiate_type + gives us. + * class.c (instantiate_type): Don't put a POINTER_TYPE to + METHOD_TYPE on an expression. Also make a copy of rhs instead of + modifying it. + +Tue Aug 6 12:58:46 1996 Jason Merrill + + * call.c (compare_ics): Handle qual_conv after lvalue_conv. + (add_builtin_candidate): Don't take enums for ++. + (build_new_method_call): Handle non-aggregates and field calls. + Move new overloading code from... + * cvt.c: Here. + + * decl.c (grokparms): Don't check default args in templates. + +Mon Aug 5 17:17:06 1996 Jason Merrill + + * cvt.c (build_new_op): Fix args to build_unary_op. + (add_builtin_candidates): Don't call type_promotes_to on float. + + * decl.c (grokparms): Check the type of the default arg. + + * cvt.c (build_new_op): Pass non-overloaded cases on rather than + returning NULL_TREE. + + * typeck.c (build_x_binary_op): Avoid doing extra work. + (build_x_unary_op): Likewise. + (build_x_conditional_expr): Likewise. + * cvt.c (build_over_call): Return. + (add_builtin_candidate): Fix MEMBER_REF. + (build_new_op): Likewise. + +Mon Aug 5 17:07:47 1996 Mike Stump + + * method.c (build_overload_name): Put bug fix into code but leave + disabled for now so we can be bug compatible with older releases + that do repeats incorrectly. In the future, we can enable it. + +Mon Aug 5 13:46:28 1996 Jason Merrill + + * cvt.c (convert_like): Don't call build_cplus_new twice. + + * call.c, cp-tree.h, cvt.c, decl2.c, init.c, method.c, pt.c, typeck.c: + Control new overloading code with -fansi-overloading. + +Sun Aug 4 15:29:11 1996 Jason Merrill + + * cvt.c (build_over_call): Call build_cplus_new. + * call.c (build_method_call): Likewise. + * typeck.c (build_function_call_real): Likewise. + (build_conditional_expr): If both operands are TARGET_EXPRs, wrap + the COND_EXPR in a TARGET_EXPR so they use the same slot. + + * cvt.c (build_up_reference): Propagate INDIRECT_BIND to + recursive calls. + * typeck.c (complete_type): Propagate + TYPE_NEEDS_{CONSTRUCTING,DESTRUCTOR}. + +Sat Aug 3 14:05:07 1996 Jason Merrill + + * cvt.c (joust): More ?: kludging. Sigh. + (build_over_call): Don't try to synthesize global fns. + + * search.c (lookup_conversions): Use binfo marking. + +Sat Aug 3 12:33:42 1996 Bob Manson + + * search.c (build_mi_matrix): Use the correct value of cid + when determining the new mi_size. + +Sat Aug 3 01:27:41 1996 Jason Merrill + + * cvt.c (add_builtin_candidates): Do consider type conversion ops + for the first parms of += et al. + (strip_top_quals): New fn. + (reference_binding): Use it instead of TYPE_MAIN_VARIANT. + (implicit_conversion): Likewise. + (add_builtin_candidates): Be careful about arrays. + (build_new_method_call): Handle vtable optimization. + +Fri Aug 2 01:26:59 1996 Jason Merrill + + * cp-tree.h (LOOKUP_NO_TEMP_BIND): New flag. + * cvt.c (reference_binding): Use it. + (implicit_conversion): Use it. + (add_builtin_candidate, COND_EXPR): Use it. + + * cvt.c (build_new_function_call): Check for error args. + + * typeck.c (comptypes): Just check DERIVED_FROM_P, not UNIQUELY. + + * gxx.gperf: Add __null. + * hash.h: Regenerate. + * lex.h: Add RID_NULL. + * lex.c (init_lex): Create null_pointer_node here, stick it in + RID_NULL. + * decl.c (init_decl_processing): Still set its type here. + * cvt.c (cp_convert_to_pointer): Don't produce null_pointer_node. + (convert_to_pointer_force): Likewise. + (null_ptr_cst_p): Check for null_pointer_node; only accept (void*)0 + if (! pedantic). + * call.c (convert_harshness): Use null_ptr_cst_p. + * typeck.c (convert_for_assignment): Likewise. Don't produce + null_pointer_node. + + * error.c (args_as_string): Handle lists of actual args, too. + * cvt.c (null_ptr_cst): Support (void*)0 for now. + (build_user_type_conversion_1): Improve diagnostics. + (build_new_function_call): Likewise. + (build_object_call): Likewise. + (build_new_method_call): Likewise. Move call before def diagnostic... + (build_over_call): Here. + + * cvt.c (build_new_method_call): Don't complain about no match if + LOOKUP_SPECULATIVELY. + (build_over_call): Fix 'this' for virtual fn. + (build_new_method_call): Add diagnostic. + +Thu Aug 1 16:45:09 1996 Jason Merrill + + * cvt.c (add_function_candidate): Expect 'this' and 'in_chrg' for + constructors to be passed in. + (build_over_call): Likewise. + (build_user_type_conversion_1): Pass them in. + (convert_like): Likewise. + (build_object_call): Handle overloaded conversions. + (build_over_call): Pass the right args to build_vfn_ref. + (standard_conversion): Fix pmf convs. + (joust): Handle comparing statics and non-statics. + (build_new_method_call): New fn. + * call.c (build_method_call): Call it if NEW_OVER. + +Thu Aug 1 16:06:14 1996 Mike Stump + + * lex.c (do_identifier): Don't use %O on IDENTIFIER_OPNAME_Ps, use + %D instead. + +Thu Aug 1 15:24:02 1996 Mike Stump + + * except.c (expand_throw): Use maybe_build_cleanup_and_delete + instead of just maybe_build_cleanup so that we deallocate the + thrown object. + +Thu Aug 1 15:18:00 1996 Brendan Kehoe + + * decl2.c (finish_prevtable_vardecl): Make non-static for pt.c's use. + * cp-tree.h (finish_prevtable_vardecl): Add decl. + +Thu Aug 1 11:53:51 1996 Bob Manson + + * pt.c (instantiate_class_template): Call complete_type. Also, if + we're at the end of the file and we just instantiated a template + class with a vtable, call finish_prevtable_vardecl. + + * error.c (dump_decl): Don't explode (or explode more gracefully + as appropriate) if the object being dumped has a null type. + (dump_expr): Likewise. + + * search.c (build_mi_matrix): Ensure that mi_size is large enough, + by counting the number of nodes that we'll need before allocating + the array. + (lookup_fnfields): Fix comment. + (breadth_first_search): Fix comment. + +Wed Jul 31 09:57:05 1996 Jason Merrill + + * pt.c (instantiate_class_template): Propagate TYPE_PACKED and + TYPE_ALIGN. + * class.c (finish_struct): Call cplus_decl_attributes here. + (finish_struct_1): Not here. + * cp-tree.h: Adjust. + + * pt.c (type_unification): New parameter STRICT. + (unify): If STRICT, don't allow cv addition or base deduction. + * call.c, class.c, cvt.c, cp-tree.h: Adjust. + +Tue Jul 30 13:06:13 1996 Jason Merrill + + * search.c (get_template_base{_recursive}): New fns. + * pt.c (more_specialized): New fn. + (do_function_instantiation): Use it. + (unify): Handle base deduction. + * cvt.c (joust): Use more_specialized. + Don't arbitrarily choose between non-builtin candidates. + (build_over_call): Call require_complete_type. + + * decl.c (start_function): Statics are static even in a #pragma + interface file. + + * decl2.c (import_export_vtable): Disable vtable heuristic on + systems with ASM_OUTPUT_EXTERNAL. + + * cvt.c (compare_ics): Fix comparison of PMEM_CONV and BASE_CONV. + (standard_conversion): No std conv to enum type. + + * cvt.c (standard_conversion): Fix order of args to DERIVED_FROM_P + for ptm's. + + * cvt.c (reference_binding): Bind directly to a base subobject of + a class rvalue. + + * cvt.c (build_new_op): Enforce access control. + +Tue Jul 30 09:22:53 1996 Bob Manson + + * typeck2.c (process_init_constructor): When scanning the + union for a named field, skip things that aren't FIELD_DECLs. + + * method.c (synthesize_method): Don't scan fndecl's rtl if + we're at the end of the file; just assume the function can't + be inlined. + +Mon Jul 29 15:48:30 1996 Jason Merrill + + * cvt.c (build_builtin_candidate): Stick a dummy conversion in if + it failed. + + * cvt.c (build_user_type_conversion_1): Handle overloaded + conversion ops. + + * cvt.c (add_builtin_candidates): Don't consider type conversion + operators for the first parameter of operator=. + +Mon Jul 29 15:33:55 1996 Bob Manson + + * typeck.c (complete_type): Only call layout_type if we're not + expanding a template. + +Mon Jul 29 14:40:38 1996 Jason Merrill + + * cvt.c (compare_ics): Oops. + + * cvt.c (op_error): Oops. + + * cp-tree.def: Add RVALUE_CONV, rename EXACT_CONV to IDENTITY_CONV. + * cvt.c: Add IDENTITY_RANK before others. Use real_lvalue_p. + (build_conv): Use them. + (implicit_conversion): Use them. + (convert_like): Handle them. + (build_new_op): Handle builtin COND_EXPR again. + (add_builtin_candidates): Strip cv-quals. Fix oops. Include enums + in lists of types for COND_EXPR. + (add_builtin_candidate): Add enum candidates for COND_EXPR. + +Mon Jul 29 12:05:40 1996 Bob Manson + + * typeck.c (build_modify_expr): Always attempt to build a call to + the assignment operator, even if we're using a default one. + (convert_for_initialization): Call complete_type. + +Mon Jul 29 11:25:08 1996 Jason Merrill + + * cvt.c (reference_binding): A REF_BIND gets the reference type. + (implicit_conversion): Likewise. + (convert_like): Likewise. + (compare_ics): Likewise. + (compare_qual): Likewise. + (print_z_candidates): Handle no candidates. + (build_new_op): Don't handle builtin COND_EXPR for now. + +Sat Jul 27 11:27:47 1996 Stan Shebs + + * cvt.c (build_builtin_candidate): Init local var in an ANSI way. + +Fri Jul 26 01:07:22 1996 Jason Merrill + + * cvt.c (joust): If the candidates are the same, arbitrarily pick one. + + * cvt.c (build_builtin_candidate): Oops. + (build_new_op): Oops. + + * method.c (build_opfncall): Pass COND_EXPR on. + * cvt.c (build_builtin_candidate): Reorganize, support COND_EXPR. + (add_builtin_candidate{,s}): Likewise. + (add_builtin_candidates): Likewise. + (print_z_candidates, op_error, build_new_op): Likewise. + (type_decays_to): New fn. + * lex.c (init_lex): Just say ?: for COND_EXPR. + +Thu Jul 25 09:33:33 1996 Jason Merrill + + * typeck.c (complete_type): Call layout_type rather than building + a new array type. + + * cvt.c (add_builtin_candidate): Pointer arithmetic candidates + only use ptrdiff_t. + +Wed Jul 24 12:45:08 1996 Jason Merrill + + * cvt.c: Always compile the new overloading code (but don't use it). + (implicit_conversion): Add a BASE_CONV when converting to + the same class type. + (convert_like): Handle BASE_CONV. + +Tue Jul 23 12:46:30 1996 Jason Merrill + + * cvt.c (build_new_op): Support {MAX,MIN}_EXPR. + (add_builtin_candidate): Likewise. + + NEW_OVER changes: + * typeck.c (build_x_function_call): Try an operator function + whenever we call an object of class type. + * method.c (build_opfncall): Pass CALL_EXPRs through. + * cvt.c (implicit_conversion): Do const-ref case first. + (add_conv_candidate, build_object_call, op_error): New fns. + (ptr_complete_ob, TYPE_PTROB_P): void is not an object type. + ({add,build}_builtin_candidate{,s}, print_z_candidates): Display + builtin candidates. + (build_new_op): Handle CALL_EXPR. Don't try to decay void. + Fall back on preincrement handling. Use op_error. + Handle warn_synth. + (convert_like): Pass INDIRECT_BIND. Don't try to do anything with + an error_mark_node. + (build_over_call): Handle PROMOTE_PROTOTYPES and ellipsis promotions + properly. + +Mon Jul 22 16:21:55 1996 Bob Manson + + * pt.c (tsubst_expr): Handle CONTINUE_STMT. + +Mon Jul 22 15:38:58 1996 Mike Stump + + * typeck.c (build_component_ref_1): Use build_component_ref + instead of open coding it here. + +Mon Jul 22 12:18:54 1996 Jason Merrill + + * g++.c (main): Don't link with -lg++. + + NEW_OVER changes: + * cvt.c (convert_to_reference): Don't use convert_from_reference on + result of build_type_conversion. + (cp_convert): Only call build_method_call for ctors if + build_type_conversion failed. + (ptr_complete_ob): New function. + (TYPE_PTR{,OB,MEM}_P): New macros. + ({add,build}_builtin_candidate{,s}): New functions. + (print_z_candidates): Handle builtins. + (build_user_type_conversion_1): Don't use conversion fns for + converting to a base type. + (build_user_type_conversion_1): Set ICS_USER_FLAG on AMBIG_CONVs. + (build_user_type_conversion): Use convert_from_reference. + (build_new_op): New function. + (build_over_call): Fix handling of methods. + (compare_ics): Handle AMBIG_CONV properly. + * typeck2.c: Increment abort count. + * method.c (build_opfncall): Forward most requests to build_new_op. + * cp-tree.h (IS_OVERLOAD_TYPE): Tweak. + +Fri Jul 19 17:59:29 1996 Brendan Kehoe + + * error.c (dump_expr, case CONSTRUCTOR, case CAST_EXPR): Take out + invalid second argument to dump_expr_list. + +Fri Jul 19 14:04:05 1996 Mike Stump + + * decl.c (lookup_name_real): Make sure we do obj->X::i correctly. + +Thu Jul 18 14:48:23 1996 Bob Manson + + * decl2.c (import_export_vtable): ASM_OUTPUT_EXTERNAL, not + ASSEMBLE_EXTERNAL. + +Mon Jul 15 17:48:43 1996 Mike Stump + + * typeck2.c (process_init_constructor): New pedwarn for using { } + to initialize a pointer to member function. + * typeck.c (build_ptrmemfunc1): Avoid use of digest_init so that + we can avoid the new error. + +Mon Jul 15 15:42:03 1996 Mike Stump + + * typeck.c (build_ptrmemfunc1): New function to hide details of + pointer to member functions better. + +Mon Jul 15 14:23:02 1996 Mike Stump + + * init.c (resolve_offset_ref): Resolve OFFSET_REFs that are + methods into the actual method, as we know the implied object is + not used. + +Mon Jul 15 13:08:29 1996 Brendan Kehoe + + * parse.y (maybecomma_warn): Only emit the pedwarn if we're not + inside a system header. + +Fri Jul 12 16:30:05 1996 Bob Manson + + * call.c (build_method_call): Call complete_type on the + instance type. + +Thu Jul 11 17:16:40 1996 Mike Stump + + * typeck.c (build_component_ref): Always build up an OFFSET_REF + for obj_ptr->func so that we can know which object to use in a + method call. + +Wed Jul 10 19:36:37 1996 Mike Stump + + * typeck.c (build_ptrmemfunc): Remove sorry, now we can cast + around things. Also improve maintainability. + +Wed Jul 10 18:20:11 1996 Bob Manson + + * decl.c (grokdeclarator): Check for overflow when evaluating an + array dimension. + +Wed Jul 10 17:26:19 1996 Jason Merrill + + * cvt.c (cp_convert): Don't check for ambiguity with constructor + if NEW_OVER. + + * typeck.c (build_x_function_call): Pass function overload + questions to new overloading code if NEW_OVER. + * init.c (expand_aggr_init_1): Only check for type conversion ops + if we're doing copy-initialization (i.e. LOOKUP_ONLYCONVERTING). + Don't check for ambiguity with constructor if NEW_OVER. + * cvt.c (convert_to_reference): Dereference the result of a type + conversion operator. + (build_conv): Propagate ICS_USER_FLAG. + (implicit_conversion): Call instantiate_type. + Pass LOOKUP_ONLYCONVERTING instead of LOOKUP_NORMAL. + (add_function_candidate): Fix cv-quals on argtype. + (print_z_candidates): New function. + (build_new_function_call): Call it. + (build_user_type_conversion_1): If LOOKUP_ONLYCONVERTING, don't + consider non-converting constructors. + Call print_z_candidates. + Return an AMBIG_CONV for an ambiguous conversion. + (build_user_type_conversion): Handle AMBIG_CONV. + (convert_like): Fix test for building TARGET_EXPR. + Call instantiate_type. + Handle AMBIG_CONV and LVALUE_CONV. + (build_over_call): Handle 0 args and ellipsis. + * cp-tree.def: Add AMBIG_CONV. + +Tue Jul 9 17:48:48 1996 Mike Stump + + * decl.c (lookup_name_real): If we find mem in obj when parsing + `obj->mem', make sure we return the right value. + +Tue Jul 9 16:11:28 1996 Bob Manson + + * search.c (get_base_distance): Call complete_type. + +Tue Jul 9 12:46:34 1996 Mike Stump + + * decl.c (store_bindings): Make static. + +Mon Jul 8 16:42:31 1996 Jason Merrill + + * init.c (expand_aggr_init_1): Don't check type conversions if + NEW_OVER. + + * cvt.c (z_candidate): Put back template field. + (add_function_candidate): Set it. + (add_template_candidate): Likewise. + (joust): Use it. + (compare_qual): Handle references and pointers to members. + (compare_ics): Handle reference bindings. + + * decl.c (duplicate_decls): Propagate DECL_ONE_ONLY. + +Mon Jul 8 16:18:56 1996 Bob Manson + + * call.c (compute_conversion_costs): Call complete_type. + + * tree.c (vec_binfo_member): Use comptypes instead of comparing + pointers, so we can handle template parameters. + +Fri Jul 5 16:51:53 1996 Bob Manson + + * cvt.c (cp_convert_to_pointer): We have to call complete_type + here; let's make it explicit instead of a side effect of an + error check. + +Wed Jul 3 16:29:51 1996 Jason Merrill + + * cvt.c (z_candidate): Remove template field. + (reference_binding): Handle binding to temporary. + (implicit_conversion): Likewise. + (add_function_candidate): Handle artificial constructor parms. + Handle functions with too few parms. + (add_template_candidate): New function. + (build_user_type_conversion_1): Handle constructors. + (convert_like): Likewise. + (build_over_call): Likewise. + (build_new_function_call): Support templates. + (compare_ics): Fix reference, inheritance handling. + +Mon Jul 1 22:58:18 1996 Bob Manson + + * decl.c: Add signed_size_zero_node. + (init_decl_processing): Build it. + * class.c (prepare_fresh_vtable): Use it instead of size_zero_node + when we're trying to make a negative delta. + +Mon Jul 1 17:56:19 1996 Brendan Kehoe + + Stop doing this damn index==strchr variable name confusion. + * class.c (add_virtual_function): Change local var INDEX to be + named IDX. + (add_method): Likewise. + * lex.c (print_parse_statistics): Likewise. + * search.c (make_memoized_table_entry): Likewise. + (lookup_fnfields_here): Likewise. + (lookup_field): Likewise. + (lookup_fnfields): Likewise. + (get_baselinks): Likewise. + * sig.c (build_signature_table_constructor): Likewise. + (build_signature_method_call): Likewise. + * typeck.c (build_x_array_ref): Change INDEX parm to be named IDX. + (get_member_function_from_ptrfunc): Likewise. + (build_ptrmemfunc): Change local var INDEX to be IDX. + (c_expand_start_case): Likewise. + +Sat Jun 29 14:05:46 1996 Jason Merrill + + * cvt.c (cp_convert_to_pointer): Move user-defined type conversion + handling to before extraction of TYPE_PTRMEMFUNC_FN_TYPE. + (convert_to_reference): Use build_type_conversion to convert to + the reference type directly. + (standard_conversion): Fix void* case, non-conversions. + (reference_binding): Fix expr == 0 case, non-conversions. + (convert_like): Support REF_BIND. + (compare_qual): Split out from compare_ics. + (compare_ics): Use it, handle icses with only a qual_conv. + + * init.c (expand_vec_init): Don't crash if decl is NULL. + +Fri Jun 28 11:52:51 1996 Stan Shebs + + * mpw-config.in: New file, configury for Mac MPW. + * mpw-make.sed: New file, makefile editing for MPW. + +Thu Jun 27 15:18:30 1996 Jason Merrill + + * pt.c (instantiate_class_template): Call repo_template_used. + + * search.c (lookup_conversions): Only lookup conversions in + complete types. + +Thu Jun 27 12:59:53 1996 Brendan Kehoe + + * cp-tree.def: Renamed from tree.def, to avoid confusion with + gcc's tree.def. + * cp-tree.h, lex.c: Include cp-tree.def. + * Makefile.in (CXX_TREE_H): Reference cp-tree.def. + +Wed Jun 26 18:29:47 1996 Bob Manson + + * init.c (build_vec_delete_1): Call complete_type. + +Mon Jun 24 17:17:32 1996 Mike Stump + + * except.c (start_anon_func): Make sure anonymous functions are + never external. + +Fri Jun 21 15:10:58 1996 Jason Merrill + + * decl.c (finish_function): If function_depth > 1, set nested. + + * decl2.c (grokbitfield): Revert Bob's change. + * class.c (finish_struct_1): Fix handling of named bitfield widths. + +Thu Jun 20 23:35:38 1996 Jason Merrill + + * pt.c (add_pending_template): Handle types. + (lookup_template_class): With -fexternal-templates, just add the class + to pending_templates instead of instantiating it now. + * decl2.c (finish_file): Handle types in pending_templates. + +Thu Jun 20 14:08:40 1996 Bob Manson + + * decl2.c (grokbitfield): Handle constant decls appropriately. + Give an appropriate error message now instead of spewing core + later. + +Thu Jun 20 13:01:51 1996 Jason Merrill + + * decl2.c: Don't turn on thunks by default for now. + +Wed Jun 19 11:37:04 1996 Jason Merrill + + * typeck.c (complete_type): Handle error_mark_node. + (common_type, OFFSET_TYPE): Handle template_type_parms. + +Tue Jun 18 10:02:15 1996 Jason Merrill + + * pt.c (instantiate_decl): If at_eof, call import_export_decl + regardless of DECL_INLINE. + + * typeck.c (mark_addressable): Set TREE_ADDRESSABLE on CONSTRUCTORs. + + * class.c (finish_struct_bits): Copy TYPE_SIZE. + + * rtti.c (build_dynamic_cast): Support templates. + * tree.def: Support DYNAMIC_CAST_EXPR. + * pt.c (tsubst_copy): Likewise. + * decl2.c (build_expr_from_tree): Likewise. + +Mon Jun 17 15:23:36 1996 Jason Merrill + + * typeck.c (build_static_cast): Support templates. + (build_const_cast): Likewise. + * tree.def: Support CONST/STATIC_CAST_EXPR. + * pt.c (tsubst_copy): Likewise. + * decl2.c (build_expr_from_tree): Likewise. + +Sun Jun 16 12:33:57 1996 Jason Merrill + + * decl2.c (finish_vtable_vardecl): Don't trust + TREE_SYMBOL_REFERENCED for vtables of local classes. + +Fri Jun 14 18:13:36 1996 Jason Merrill + + * pt.c (tsubst_copy): Handle operator T. + +Wed Jun 12 17:52:40 1996 Brendan Kehoe + + * init.c (build_delete): Move creation of PARMS inside test of + TYPE_HAS_DESTRUCTOR, since it's never used outside of that block. + +Tue Jun 11 15:09:18 1996 Bob Manson + + * typeck.c (build_conditional_expr): Don't assume that + the arguments to ?: are always pointers or records. + +Tue Jun 11 13:56:23 1996 Jason Merrill + + * decl2.c (import_export_decl): Still emit static/weak/comdat + copies of inline template functions with -fno-implicit-templates. + +Tue Jun 11 11:42:13 1996 Bob Manson + + * init.c (build_delete): Determine the complete basetype + path to the destructor we're calling. + +Fri Jun 7 15:30:10 1996 Bob Manson + + * decl.c (build_enumerator): Always copy the INTEGER_CST used to + initialize the enum, because we really and truly don't know where + it came from. + (start_enum): Don't copy integer_zero_node because + build_enumerator will do it. + +Fri Jun 7 11:11:09 1996 Jason Merrill + + * decl.c (finish_function): Do access control on base destructors. + + * pt.c (tsubst, case FUNCTION_DECL): Set up + IDENTIFIER_GLOBAL_VALUE for member functions so pushdecl doesn't + hose us. + +Fri Jun 7 10:37:33 1996 Mike Stump + + * cvt.c (build_up_reference): If we have already extended the + lifetime of the temporary, don't try it again. + * typeck.c (c_expand_return): Don't try and convert the return + value twice when we want a reference, once is enough. + +Tue Jun 4 15:41:45 1996 Jason Merrill + + * pt.c (tsubst_expr, case DECL_STMT): Don't pass + LOOKUP_ONLYCONVERTING at all for now. + + * search.c (add_conversions): Put the conversion function in + TREE_VALUE, the basetype in TREE_PURPOSE. + * cvt.c (build_type_conversion): Adjust. + * cvt.c (build_expr_type_conversion): Adjust. + * call.c (user_harshness): Adjust. + +Mon Jun 3 15:30:52 1996 Jason Merrill + + * method.c (emit_thunk): Pretend this is a FUNCTION_DECL for the + backend's benefit. + +Mon Jun 10 18:58:19 1996 Mike Stump + + * except.c (expand_start_catch_block): Add a dummy region, if we + get an error, so that we can avoid core dumping later. + +Fri May 31 14:56:13 1996 Mike Stump + + * cp-tree.h (OFFSET_REF): Remove. + * tree.def (CP_OFFSET_REF): Rename to OFFSET_REF. + * expr.c (cplus_expand_expr): Cleanup callers of expand_expr. + * init.c (expand_aggr_init_1): Likewise. + (build_new): Likewise. + * typeck.c (expand_target_expr): Likewise. + +Fri May 31 14:22:08 1996 Jason Merrill + + * typeck.c (build_modify_expr): Don't use TREE_VALUE on a + TARGET_EXPR. + +Wed May 29 17:04:33 1996 Mike Stump + + * cvt.c (build_up_reference): Redo how and when temporaries are + created. + * decl.c (grok_reference_init): Don't try and be smart about + running cleanups. + +Wed May 29 16:02:08 1996 Mike Stump + + * cvt.c (build_up_reference): Add NULL_TREE to all calls to build + (TARGET_EXPR...), now that it has 4 arguments. + * tree.c (build_cplus_new): Likewise. + +Thu May 23 16:40:30 1996 Jason Merrill + + * error.c (dump_expr, case CAST_EXPR): Handle T() properly. + + * pt.c (instantiate_decl): Don't call push/pop_cp_function_context. + * decl.c (struct saved_scope): Remove named_labels, + {base,member}_init_list. + (maybe_push_to_top_level): Don't set them. Call + push_cp_function_context if appropriate. + (pop_from_top_level): Likewise. + + * method.c (do_build_assign_ref): Remove obsolete check of + TYPE_HAS_ASSIGN_REF (basetype). + + * decl.c (grokfndecl): Diagnose user definition of + implicitly-declared methods. + +Thu May 23 12:13:08 1996 Bob Manson + + * method.c (do_build_copy_constructor): Add code to give + meaningful error messages instead of crashing. + (do_build_assign_ref): Don't synthesize assignment operators for + classes containing reference or const members. + + * class.c (struct base_info): Remove cant_synth_copy_ctor + and cant_synth_asn_ref. + (finish_base_struct): Remove the code that tries to conditionalize + synthesis of copy constructors & assignment operators based on + access permissions. Instead, let it fail when it tries to + synthesize the copy constructor. This will give meaningful error + messages instead of silently generating code to perform a bitcopy. + +Wed May 22 11:45:19 1996 Bob Manson + + * lex.c (real_yylex): Remove old-n-crufty #if 0 code for + determining types for constant values. + + * decl.c (struct named_label_list): Use instead of stuffing + random items into a TREE_LIST node. + (named_label_uses): Use the new struct. + (poplevel): Likewise. + (lookup_label): Likewise. + (define_label): Add an error message to tell the user the line + where the goto is located in addition to the destination of the + goto. + (init_decl_processing): Use NULL instead of NULL_TREE to initialize + named_label_uses. + (finish_function): Likewise. + + (start_decl): Complain about defining a static data member + in a different type from which it was declared. + +Wed May 22 09:33:23 1996 Jason Merrill + + * cvt.c (build_expr_type_conversion): Adjust. + +Tue May 21 11:21:56 1996 Jason Merrill + + * call.c (build_method_call): Always convert 'this' to the + appropriate type. + + * search.c (add_conversions): Put the conversion function in + TREE_VALUE, the type in TREE_PURPOSE. + * cvt.c (build_type_conversion): Adjust. + * call.c (user_harshness): Adjust. + + * method.c (emit_thunk): Call temporary_allocation and + permanent_allocation around the ASM_OUTPUT_MI_THUNK case, too. + + * tree.c (build_cplus_array_type): Handle tweaking of + TYPE_MAIN_VARIANT here. + * typeck.c (common_type): Not here. + + * typeck.c (complete_type): Only try to complete an array type if + it has a domain. + +Mon May 20 14:55:59 1996 Jason Merrill + + * decl.c (grokvardecl): Call complete_type. + (grokdeclarator): Call complete_type for PARM_DECLs. + +Fri May 17 16:41:17 1996 Jason Merrill + + * pt.c (instantiate_class_template): Re-set + CLASSTYPE_GOT_SEMICOLON after calling finish_struct_1. + +Fri May 17 14:56:55 1996 Mike Stump + + * cp-tree.h (cp_expand_decl_cleanup): Remove, the backend is now + smart enough to do it right. + * tree.c (cp_expand_decl_cleanup): Likewise. + * decl.c (cp_finish_decl): Use expand_decl_cleanup instead of + cp_expand_decl_cleanup. + (store_parm_decls): Likewise. + (hack_incomplete_structures): Likewise. + * except.c (push_eh_cleanup): Likewise. + +Fri May 17 13:13:51 1996 Mike Stump + + * expr.c (expand_expr, cond UNSAVE_EXPR): Move from the C++ + frontend to the backend where it belongs. + * tree.c (unsave_expr): Likewise. + (unsave_expr_now): Likewise. + * tree.def (UNSAVE_EXPR): Likewise. + * cp-tree.h (unsave_expr): Likewise. + (unsave_expr_now): Likewise. + +Fri May 17 11:02:41 1996 Mike Stump + + * init.c (emit_base_init): Make sure the partial EH cleanups live + on the function_obstack. + +Thu May 16 15:29:33 1996 Bob Manson + + * expr.c (do_case): Don't try to dereference null TREE_TYPEs + when checking for pointer types. + +Thu May 16 13:38:58 1996 Jason Merrill + + * pt.c (instantiate_class_template): Remove obsolete check for + access declarations. + +Thu May 16 13:34:15 1996 Mike Stump + + * call.c (build_overload_call): Simplify calls to + build_overload_call by removing last parameter. + (build_method_call): Likewise. + * cp-tree.h: Likewise. + * method.c (build_opfncall): Likewise. + * typeck.c (build_x_function_call): Likewise. + +Thu May 16 13:15:43 1996 Mike Stump + + * call.c (default_parm_conversions): Factor out common code. + (build_method_call): Use it. + (build_overload_call_real): Use it. + +Wed May 15 14:46:14 1996 Mike Stump + + * call.c (build_method_call): Allow implicit & on METHOD_TYPEs, + but pedwarn as the code is bogus. + * typeck.c (decay_conversion): Likewise. + (build_function_call_real): Use build_addr_func instead of + default_conversion. Don't allow pointer-to-method functions down + here. + (build_unary_op): Use real pointer-to-member functions instead of + fake ones. + (build_ptrmemfunc): Use build_addr_func instead of build_unary_op. + (convert_for_assignment): Removed some obsolete code. + * decl2.c (reparse_absdcl_as_expr): Pass current_class_ref to + build_x_function_call instead of current_class_ptr. Only call + digest_init once on an initializer, we do this just checking + TREE_TYPE. + (build_expr_from_tree): Pass current_class_ref to + build_x_function_call instead of current_class_ptr. + * init.c (build_member_call): Likewise. + * pase.y: Likewise. + * error.c (dump_expr): Handle OFFSET_REFs better. + * pt.c (unify): Handle pointer-to-member functions better. + * decl.c (finish_function): Clear out current_class_ref just like + we do for current_class_ptr. + + * typeck.c (get_delta_difference): Handle virtual bases better. + +Tue May 14 16:37:37 1996 Jason Merrill + + * sig.c (build_signature_table_constructor): Use the delta for + the original basetype for this virtual function with thunks. + (build_signature_method_call): We still need to adjust 'this' + with thunks. + +Tue May 14 16:27:25 1996 Mike Stump + + * call.c (build_addr_func): New routine. Used to get the `real' + address of a function or a method. Needed to avoid getting a + pointer-to-member function. + (build_call): New routine to build CALL_EXPRs. + (build_method_call): Use it. + * cvt.c (convert_to_aggr): Likewise. + * typeck.c (build_function_call_real): Likewise. + * sig.c (build_signature_table_constructor): Use build_addr_func. + * cp-tree.h (build_call, build_addr_func): Declare them. + +Tue May 14 12:47:47 1996 Mike Stump + + * cp-tree.h (LOOKUP_AGGR): Remove, unused. + * parse.y: Remove uses of LOOKUP_AGGR. + +Tue May 14 12:07:51 1996 Mike Stump + + * *.[chy]: Rename current_class_decl to current_class_ptr, and + C_C_D to current_class_ref. + +Mon May 13 16:55:23 1996 Jason Merrill + + * call.c (convert_harshness): Tighten up pointer conversions. + +Sat May 11 04:33:50 1996 Doug Evans + + * decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef. + (finish_file): Likewise. + +Fri May 10 11:09:57 1996 Jason Merrill + + * cvt.c (convert_fn_ptr): We don't use thunks for pmfs. + + * method.c (emit_thunk): Set flag_omit_frame_pointer in default + code. + +Thu May 9 18:18:30 1996 Jason Merrill + + * decl2.c: Turn on thunks by default where supported. + +Tue May 7 20:39:57 1996 Mike Stump + + * cp-tree.h (build_overload_call_maybe): Removed. + * call.c (build_overload_call_real): Invert meaning of last arg to + be require_complete. + (build_overload_call): Likewise. + * typeck.c (build_x_function_call): Use build_overload_call_real + instead of build_overload_call_maybe. + +Mon May 6 01:23:32 1996 Jason Merrill + + * decl2.c (finish_file): Don't try to emit functions that haven't + been compiled. + +Fri May 3 09:30:13 1996 Jason Merrill + + * decl2.c (finish_vtable_vardecl): Oops. + + * decl.c (maybe_push_to_top_level): Do save previous_class_*. + Also store the bindings from previous_class_values. + (pop_from_top_level): Restore them. + +Thu May 2 21:56:49 1996 Jason Merrill + + * decl2.c (finish_vtable_vardecl): Only write out vtable if its + symbol has been referenced. + (finish_file): Re-join synthesis/vtable loop with inline emission + loop, disable inlining when an inline is output. + +Thu May 2 17:20:02 1996 Mike Stump + + * except.c (init_exception_processing): Setup saved_in_catch. + (push_eh_cleanup): Reset __eh_in_catch. + (expand_start_catch_block): Set __eh_in_catch. + +Thu May 2 16:21:17 1996 Mike Stump + + * except.c (push_eh_cleanup): Add tracking for whether or not we + have an active exception object. + (expand_builtin_throw): Use it to make sure a rethrow without an + exception object is caught. + +Thu May 2 11:26:41 1996 Jason Merrill + + * decl.c (maybe_push_to_top_level): Clear out class-level bindings + cache. + +Wed May 1 11:26:52 1996 Jason Merrill + + * decl2.c (finish_file): Also use sentries for vars with + DECL_ONE_ONLY or DECL_WEAK set (should any such happen to be + created). + + * lex.c (handle_cp_pragma): Disable #pragma + interface/implementation if SUPPORTS_ONE_ONLY > 1. + +Tue Apr 30 11:25:46 1996 Jason Merrill + + * method.c (emit_thunk): Wrap default case in + temporary/permanent_allocation. + + * method.c (make_thunk): Use DECL_ONE_ONLY. + (emit_thunk): Call assemble_end_function. + +Mon Apr 29 15:38:29 1996 Jason Merrill + + * decl2.c (import_export_vtable): Use DECL_ONE_ONLY. + (import_export_decl): Likewise. + (finish_prevtable_vardecl): Disable vtable hack if + SUPPORTS_ONE_ONLY > 1. + +Mon Apr 29 14:32:47 1996 Mike Stump + + * typeck.c (build_modify_expr): PREINCREMENT_EXPR and + PREDECREMENT_EXPRs take two arguments, not one. + +Mon Apr 29 00:27:53 1996 Jason Merrill + + * class.c (build_vtable_entry): Don't build thunks for abstract + virtuals. + + * lex.c (real_yylex): Fix handling of __PRETTY_FUNCTION__ like C + frontend. + +Sat Apr 27 16:45:35 1996 Jason Merrill + + * class.c (set_rtti_entry): Use size_zero_node. + (build_vtable): Likewise. + +Sat Apr 27 14:48:57 1996 Jason Merrill + + * class.c (finish_struct_1): Pass size_zero_node to set_rtti_entry. + (prepare_fresh_vtable): Likewise. + +Fri Apr 26 13:14:14 1996 Jason Merrill + + * method.c (emit_thunk): Call mark_used on the target function. + + * call.c (build_method_call): Don't warn about pending templates. + +Thu Apr 25 14:55:44 1996 Jason Merrill + + * decl2.c (finish_file): Fix list walking logic. + + * typeck2.c (check_for_new_type): Only warn if -pedantic. + +Wed Apr 24 15:41:15 1996 Bob Manson + + * class.c (finish_struct_1): Remove old code for + dont_allow_type_definitions. + * cp-tree.h: Likewise. + * spew.c: Make sure cp-tree.h is included before parse.h, so the + definition of flagged_type_tree is found before it is used. + * lex.c: Likewise. + * parse.y: Added the ftype member to the type union, and changed a + number of rules to use it instead of ttype. Added calls to + check_for_new_type() as appropriate. + * typeck2.c (check_for_new_type): New function for checking + if a newly defined type appears in the specified tree. + * cp-tree.h: Add new type flagged_type_tree. Add a prototype + for check_for_new_type(). + +Wed Apr 24 00:36:21 1996 Jason Merrill + + * decl2.c (finish_file): Only use a sentry if the decl is public. + + * pt.c (tsubst_expr, DECL_STMT): If we don't have an initializer, + don't pass LOOKUP_ONLYCONVERTING. + +Tue Apr 23 17:18:47 1996 Bob Manson + + * typeck.c (common_type): Fix the ARRAY_TYPE case so it + properly keeps track of const and volatile type modifiers. + +Tue Apr 23 10:52:56 1996 Jason Merrill + + * tree.c (cp_tree_equal): C++ version of simple_cst_equal. + * pt.c (comp_template_args): Use it. + + * rtti.c (get_tinfo_fn, build_dynamic_cast, expand_*_desc): Call + assemble_external for artificial function decls. + + * decl.c (cp_finish_decl): Oops. + +Mon Apr 22 17:28:27 1996 Jason Merrill + + * decl2.c (import_export_decl): Put static data member templates + into common storage, or make them weak, depending on whether they + are dynamically or statically initialized. + (get_sentry): New function. + (finish_file): Do import_export_decl for static data members before + building the init/fini functions. Don't init/fini a variable that's + EXTERNAL. Use a sentry for variables in common. Fix mismatching + push/pop_temp_slots. + * decl.c (cp_finish_decl): If DECL_NOT_REALLY_EXTERN, do the + expand_static_init thang. + * method.c (get_id_2): New function. + +Mon Apr 22 15:32:45 1996 Bob Manson + + * parse.y (empty_parms): Make sure we use C++-style prototypes + when we're declaring member functions. + +Sun Apr 21 10:08:22 1996 Jason Merrill + + * Makefile.in (CONFLICTS): 16 s/r conflicts. + * parse.y (self_template_type): New nonterminal. + +Thu Apr 18 08:56:54 1996 Jason Merrill + + * decl.c (make_typename_type): Handle getting a TYPE_DECL for a + name. + * parse.y (base_class.1): Allow 'typename foo::bar'. + + * lex.c (check_newline): Remove #pragma code that plays with the + input stream, since we now deal with tokens. Clear nextchar when + we're done. + (handle_cp_pragma): Use real_yylex. + (handle_sysv_pragma): Don't do skipline here. Only call real_yylex + in one place. + + * lex.c (check_for_missing_semicolon): Handle SELFNAME. + + * lex.c (handle_cp_pragma): Fix "#pragma implementation". + +Wed Apr 17 16:51:33 1996 Jason Merrill + + * parse.y: New token SELFNAME for potential constructor. + * spew.c (yylex): Handle it. + * lex.c (identifier_type): Produce it. + + * parse.y (complete_type_name): In :: case, don't push class binding. + (complex_type_name): Likewise. + +Wed Apr 17 15:02:40 1996 Mike Stump + + * typeck.c (build_reinterpret_cast): Handle pointer to member + functions. + +Wed Apr 17 12:28:26 1996 Brendan Kehoe + + * lex.c (handle_cp_pragma): New function, with decl, doing the cc1plus + pragmas. + (check_newline): Put the vtable/unit/implementation/interface pragma + code into handle_cp_pragma, replacing it with a call. + (handle_sysv_pragma): Give int return type, and take FINPUT and TOKEN + args. Get the next token after handling the pragma token. + +Wed Apr 17 10:28:34 1996 Jason Merrill + + * cvt.c (cp_convert_to_pointer): Avoid doing base analysis on pmfs. + (convert_to_pointer_force): Likewise. + + * init.c (build_new): Fix array new without -fcheck-new. + +Tue Apr 16 13:44:58 1996 Jason Merrill + + * cp-tree.h, call.c, class.c, decl.c, parse.y, pt.c, rtti.c, + tree.c: Lose TYPE_NESTED_NAME. + + * parse.y (nested_name_specifier_1): Don't treat non-identifiers + as identifiers. + + * tree.def: Add VEC_INIT_EXPR. + * expr.c (cplus_expand_expr): Handle it. + * init.c (build_new): Use it instead of the RTL_EXPR nastiness and + the extra file-scope symbol nastiness. + +Mon Apr 15 16:21:29 1996 Jason Merrill + + * method.c (make_thunk): Thunks are static. + (emit_thunk): Use ASM_OUTPUT_MI_THUNK if it's defined. + + * decl2.c (mark_vtable_entries): Emit thunks as needed. + (finish_file): Don't emit them here. + +Sun Apr 14 11:34:39 1996 Jason Merrill + + * rtti.c (build_dynamic_cast): Handle null pointers. + (ifnonnull): New function. + +Fri Apr 12 09:08:27 1996 Bob Manson + + * call.c (build_method_call): Remember the original basetype we + were called with. Give an error message instead of trying + (incorrectly) to call a non-static member function through a + non-inherited class. + + * search.c (expand_upcast_fixups): Mark the new fixup as + DECL_ARTIFICIAL. + +Thu Apr 11 03:57:09 1996 Jason Merrill + + * init.c (build_new): Use a TARGET_EXPR for alloc_expr. + + * class.c (set_rtti_entry): Fix for thunks. + + * decl2.c (import_export_decl): Still emit typeinfo fns for + cv-variants of builtin types. + + * rtti.c (expand_class_desc): Set up base_info_type_node here. + (init_rtti_processing): Instead of here. + +Wed Apr 10 14:17:13 1996 Jason Merrill + + * rtti.c (init_rtti_processing): Do init regardless of -frtti. + (build_typeid): Only complain about taking dynamic typeid without + -frtti. + + * decl2.c: flag_rtti defaults to 1. + + * rtti.c (get_tinfo_var): The general class case is now smaller. + (init_rtti_processing): Pack the latter three fields of base_info + into 32 bits. + +Wed Apr 10 13:50:14 1996 Mike Stump + + * init.c (expand_member_init): Don't dump if name is NULL_TREE. + +Wed Apr 10 12:56:02 1996 Mike Stump + + * search.c (make_memoized_table_entry): Undefer the pop, if necessary. + (push_memoized_context): Split out code to undefer pop_type_level to + (clear_memoized_cache): here. + (pop_memoized_context): We can only handle one layer of deferral of + pop_type_level so clear the cache, if there was a previous level. + +Tue Apr 9 23:06:09 1996 Jason Merrill + + * rtti.c (init_rtti_processing): Build up base_info_type_node. + (expand_class_desc): Use one pointer to an array of base_info + structs, passed using a CONSTRUCTOR. + +Tue Apr 9 14:20:57 1996 Mike Stump + + * class.c (build_vbase_path): Remove block extern for + flag_assume_nonnull_objects here. + (build_vfn_ref): Split out functionality into build_vtbl_ref. + (build_vtbl_ref): New routine. + (build_vtable): Set up rtti info here. + (add_virtual_function): Note in CLASSTYPE_RTTI the best + place where we can get the rtti pointers from to avoid having to + search around for a place. + (finish_base_struct): Likewise. + (finish_struct_1): Likewise. Never create totally new vtables + with totally new vtable pointers for rtti. Disable code to layout + vtable pointers better until we want to break binary + compatibility. + * rtti.c (build_headof_sub): New routine to convert down to a + sub-object that has an rtti pointer in the vtable. + (build_headof): Use it. Also, use build_vtbl_ref now to be more + maintainable. + (build_dynamic_cast): Make sure we have saved it, if we need to. + * search.c (dfs_init_vbase_pointers): Disable code that deals with + a more efficient vtable layout, enable later. + * call.c (flag_assume_nonnull_objects): Moved declaration to + * cp-tree.h: here. Declare build_vtbl_ref. + * pt.c (instantiate_class_template): Use NULL_TREE instead of 0 in + function calls that want a tree. + +Tue Apr 9 12:10:26 1996 Jason Merrill + + * rtti.c (build_dynamic_cast): Handle downcasting to X* given + other X subobjects in the most derived type. Ack. + + * rtti.c (build_dynamic_cast): No need to strip cv-quals here, + get_typeid will do it for us. + (get_typeid_1): Break out call-building for expand_*_desc to use. + (get_typeid): Call it. + (expand_*_desc): Likewise. + * decl.c (init_decl_processing): Don't set TYPE_BUILT_IN on char * + and void *. + (init_decl_processing): Lose builtin_type_tdescs lossage. + * decl2.c (finish_vtable_vardecl): Remove obsolete code. + +Mon Apr 8 17:23:23 1996 Bob Manson + + * pt.c (tsubst): When calling set_nested_typename, use + TYPE_NESTED_NAME (current_class_type) instead of + current_class_name. + + * decl.c (pushdecl): Likewise. + (pushdecl_class_level): Likewise. + (grokdeclarator): Use NULL_TREE instead of 0 in the call to + set_nested_typename. + +Sun Apr 7 10:44:31 1996 Jason Merrill + + * rtti.c (synthesize_tinfo_fn): Handle arrays. + + * cp-tree.h (DECL_REALLY_EXTERN): New macro. + +Sat Apr 6 13:56:27 1996 Jason Merrill + + * rtti.c (throw_bad_cast): Use entry point __throw_bad_cast. + (init_rtti_processing): Lose bad_cast_type. + (build_dynamic_cast): Use throw_bad_cast. + + * rtti.c (synthesize_tinfo_fn): Handle enums and pmfs. + + * decl2.c (finish_file): Don't synthesize artificial functions + that are external and not inline. + + * rtti.c (get_tinfo_fn): If at_eof, call import_export_decl. + + * decl2.c (finish_file): Handle having new inlines added to + saved_inlines by synthesis. + + * rtti.c (get_bad_cast_node): Don't require . + +Fri Apr 5 17:02:09 1996 Jason Merrill + + RTTI rewrite to initialize nodes as needed, not require that + users #include , complete functionality and reduce wasted + space. + * rtti.c (init_rtti_processing): New fn. + (build_typeid): The vtable entry is now a function. + (get_tinfo_var): New fn. + (get_tinfo_fn): Likewise. + (get_typeid): Use it. + (build_dynamic_cast): Declare and use entry point __dynamic_cast. + (build_*_desc): Rename to expand_*_desc and rewrite to use entry + points __rtti_*. + (add_uninstantiated_desc, get_def_to_follow, build_t_desc): Lose. + (synthesize_tinfo_fn): New fn. + * method.c (build_t_desc_overload): Lose. + (build_overload_with_type): More generic. + * decl.c (init_decl_processing): Call init_rtti_processing. + * class.c (set_rtti_entry): Use get_tinfo_fn. + * decl2.c (mark_vtable_entries): Mark the rtti function. + (finish_prevtable_vardecl): Don't build_t_desc. + (import_export_decl): Handle tinfo functions. + (finish_file): Likewise. + * typeck.c (inline_conversion): New fn. + (build_function_call_real): Use it. + * cp-tree.h: Add decls. + + * method.c (hack_identifier): Also convert component_refs from + references. + + * lex.c (cons_up_default_function): Use the type, not the name, in + declspecs. + + * decl2.c (import_export_vtable): Fix weak vtables. + +Fri Apr 5 13:30:17 1996 Bob Manson + + * search.c (get_base_distance_recursive): Fix access checks for + protected bases. + +Fri Apr 5 11:02:06 1996 Brendan Kehoe + + * call.c (unary_complex_lvalue): Delete unneeded decl, it's in + cp-tree.h. + (convert_harshness): Add prototypes wrapped by PROTO. + * decl2.c (grok_function_init): Likewise. + (do_toplevel_using_decl): Change to void return type. + * class.c (build_vtable_entry): Remove decl of make_thunk. + (merge_overrides): Fix order of arg definitions. + (finish_vtbls): Likewise. + (fixup_vtable_deltas): Likewise. + (modify_all_direct_vtables): Likewise. + (modify_all_indirect_vtables): Likewise. + * search.c (get_base_distance_recursive): Likewise. + (get_abstract_virtuals_1): Likewise. + (fixup_virtual_upcast_offsets): Likewise. + (lookup_fnfields_1): Add prototypes wrapped by PROTO. + * init.c (perform_member_init): Fix order of arg definitions. + (expand_aggr_init_1): Add prototypes wrapped by PROTO. + * cp-tree.h (make_thunk): Add decl. + (overload_template_name, push_template_decl): Add decls. + (do_toplevel_using_decl): Change to void return type. + (vec_binfo_member): Add decl. + +Thu Apr 4 13:33:10 1996 Brendan Kehoe + + * typeck.c (mark_addressable, convert_for_assignment, + convert_for_initialization, pointer_int_sum, pointer_diff, + unary_complex_lvalue): Add prototypes wrapped by PROTO. + (convert_sequence): #if 0 fn decl, since definition also is. + +Thu Apr 4 11:00:53 1996 Mike Stump + + * rtti.c (build_dynamic_cast): Make sure we strip qualifiers on + cast to pointer types for type searching. + +Wed Apr 3 17:10:57 1996 Brendan Kehoe + + * typeck.c (get_delta_difference): Use cp_error, not error, in the + case where BINFO == 0. + +Wed Apr 3 12:01:02 1996 Mike Stump + + * call.c (build_method_call): Fix wording of error messages so + constructors come out right. + +Tue Apr 2 16:06:59 1996 Bob Manson + + * decl.c (push_overloaded_decl): Don't warn about hidden + constructors when both the type and the function are declared + in a system header file. + +Mon Apr 1 09:03:13 1996 Bob Manson + + * class.c (finish_struct_1): Propagate the TYPE_PACKED + flag for the type to the type's fields. + +Sat Mar 30 12:14:33 1996 Brendan Kehoe + + * parse.y (complex_parmlist, ELLIPSES): Take out ARM-based warning. + +Fri Mar 29 15:51:36 1996 Bob Manson + + * class.c (base_info, finish_base_struct): Replace + needs_virtual_dtor with base_has_virtual. + + (finish_struct_1): Remove the old code that tried to make default + destructors virtual. Use base_has_virtual when checking if we need + to add a vtable entry for the rtti code. + +Fri Mar 29 14:02:36 1996 Jason Merrill + + * pt.c (push_template_decl): Complain about template decl with + inappropriate declaration. + +Fri Mar 29 12:15:35 1996 Bob Manson + + * typeck.c (build_x_unary_op): Remove bogus check for taking + the address of a member function. + +Fri Mar 29 11:56:02 1996 Jason Merrill + + * parse.y (constructor_declarator): Only push the class if + we are not already in the class. + +Fri Mar 29 09:41:02 1996 Jeffrey A. Law + + * method.c (emit_thunk): Remove current_call_is_indirect nonsense. + Add additional argument to INIT_CUMULATIVE_ARGS. + +Thu Mar 28 16:41:39 1996 Jason Merrill + + * decl.c (shadow_tag): Fix error about anon union with methods. + + * parse.y (self_reference): Only generate a self-reference if this + is a non-template class. + (opt.component_decl_list): Only use it if it was generated. + + * parse.y (component_decl_1): Use constructor_declarator. + (fn.def2): Likewise. + (notype_component_declarator0): Likewise. + +Thu Mar 28 15:11:35 1996 Bob Manson + + * typeck.c (build_x_unary_op): Add checks for taking the address + of a TARGET_EXPR or of a member function, and give appropriate + warnings. + +Thu Mar 28 14:49:26 1996 Jason Merrill + + * pt.c (process_template_parm): Allow template type parms to be + used as types for template const parms. + +Wed Mar 27 15:51:19 1996 Mike Stump + + * init.c (expand_vec_init): Ensure the eh cleanups are on the + function_obstack. + +Wed Mar 27 10:14:30 1996 Jason Merrill + + * decl.c (lookup_name_real): Be even more picky about the + ambiguous lookup warning. + (grokdeclarator): Tweak SCOPE_REF constructor declarators here. + * parse.y (constructor_declarator): Rather than here. + + * parse.y (constructor_declarator): New nonterminal. + (fn.def1): Use it. + (explicit_instantiation): Likewise. + +Tue Mar 26 13:41:33 1996 Jason Merrill + + Add implicit declaration of class name at class scope. + * decl.c (lookup_name_real): Restrict pedwarn about ambiguous lookup. + * parse.y (self_reference): New nonterminal. + (opt.component_decl_list): Use it. + (fn.def1): Add nested_name_specifier type_name cases. + * class.c (build_self_reference): New function. + (finish_struct): Handle access_default later, move self-reference + decl to the end. + * pt.c (lookup_template_class): Handle getting a TYPE_DECL. + * cp-tree.h: Adjust. + + * pt.c (do_function_instantiation): Separate handling of member + functions and non-member functions properly. + +Mon Mar 25 14:23:22 1996 Jason Merrill + + * pt.c (process_template_parm): Improve error for 'volatile class K'. + + * class.c (finish_struct_1): Check the right slot for destructors. + + * decl.c (start_enum): Complain about enum templates. + +Mon Mar 25 13:25:31 1996 Mike Stump + + * init.c (resolve_offset_ref): Offset pointers to member data by one. + * typeck.c (unary_complex_lvalue): Likewise. + +Mon Mar 25 13:30:42 1996 Bob Manson + + * typeck.c (c_expand_return): Check for a returned local + array name, similar to the check for an ADDR_EXPR. + +Mon Mar 25 13:07:19 1996 Jason Merrill + + * decl.c (cp_finish_decl): Don't build cleanups for static + variables here. + +Fri Mar 22 17:57:55 1996 Mike Stump + + * typeck.c (build_modify_expr): Fix error messages to be more + accurate. + * cp-tree.h (assop_as_string): Parallel to op_as_string, but for + assignment operators. + * error.c (assop_as_string): Likewise. Add support for `%Q' for + assignment operators. + +Fri Mar 22 13:48:29 1996 Jason Merrill + + * decl.c (grokdeclarator): Call bad_specifiers for typedefs. Also + give an error if initialized. pedwarn about nested type with the + same name as its enclosing class. + + * pt.c (tsubst, case TYPE_DECL): Set DECL_CONTEXT. + + * typeck.c (require_complete_type): Be sure to instantiate the + MAIN_VARIANT of the type. + + * decl2.c (finish_file): Instantiate pending templates before + processing static constructors and destructors. + + * pt.c (instantiate_decl): Don't instantiate functions at toplevel + unless at_eof. + +Fri Mar 22 09:30:17 1996 Bob Manson + + * decl2.c (delete_sanity): If error_mark_node is passed + in as an expression, quit while we're ahead. + + * decl.c (grokdeclarator): Give an error message if `friend' + is combined with any storage class specifiers. + +Wed Mar 20 14:51:55 1996 Jason Merrill + + * parse.y (named_complex_class_head_sans_basetype): Don't crash on + definition of nonexistent nested type. + + * error.c (dump_decl, case TYPE_DECL): Fix decision for whether or + not to say 'typedef'. + +Wed Mar 20 00:11:47 1996 Brendan Kehoe + + * cp-tree.h (struct lang_type): Make search_slot a tree, not a char*. + * search.c (dfs_walk, dfs_init_vbase_pointers, + expand_upcast_fixups): Remove cast of CLASSTYPE_SEARCH_SLOT. + (dfs_find_vbases): Remove cast for CLASSTYPE_SEARCH_SLOT init. + +Tue Mar 19 17:56:03 1996 Jason Merrill + + * except.c (build_throw): Support minimal parse. + * pt.c (tsubst_copy): Support THROW_EXPR. + * decl2.c (build_expr_from_tree): Likewise. + + * pt.c (mangle_class_name_for_template): Always allocate + scratch_firstobj. + +Tue Mar 19 16:34:31 1996 Bob Manson + + * cvt.c (cp_convert_to_pointer): Give an appropriate error + when trying to cast from an incomplete type. + +Tue Mar 19 16:00:33 1996 Jason Merrill + + * pt.c (instantiate_class_template): Don't bother setting up + CLASSTYPE_TAGS explicitly, as the nested types will add + themselves. + +Tue Mar 19 15:48:43 1996 Bob Manson + + * decl.c (shadow_tag): Remove old error check for usage of + an enum without a previous declaration. + (xref_tag): Add error message about usage of enums without a + previous declaration. + +Tue Mar 19 09:21:35 1996 Jason Merrill + + * lex.c (do_identifier): Only do name consistency check if we're + parsing. + + * pt.c (push_template_decl): Don't crash if we get a member defn + that doesn't match. + + * decl.c (xref_tag_from_type): New function to do an xref without + always having to figure out code_type_node. + * cp-tree.h: Declare it. + * pt.c (instantiate_class_template): Use it for friend classes. + (lookup_template_class): Use it. + + * typeck2.c (build_functional_cast): Pull out a single parm before + passing it to build_c_cast. + +Tue Mar 19 09:07:15 1996 Bob Manson + + * expr.c (do_case): Give an error message if a pointer is + given as a case value. + +Mon Mar 18 21:57:54 1996 Jason Merrill + + * typeck.c (build_c_cast): Don't pull single TEMPLATE_DECL out of + an overload list. + + * lex.c (cons_up_default_function): Really, now, interface hackery + does not apply to synthesized methods. + +Mon Mar 18 18:20:57 1996 Mike Stump + + * call.c (build_method_call): Ctors and dtors now have special names + with respect to lookups. + * class.c (add_method): Likewise. + (grow_method): Likewise. + (finish_struct_methods): Likewise. + (warn_hidden): Likewise. + (finish_struct_1): Likewise. + * cvt.c (convert_to_reference): Likewise. + (convert_to_aggr): Likewise. + (cp_convert): Likewise. + * decl2.c (check_classfn): Likewise. + * init.c (expand_member_init): Likewise. + (expand_default_init): Likewise. + (expand_aggr_init_1): Likewise. + (build_offset_ref): Likewise. + (build_new): Likewise. + (build_delete): Likewise. + * lex.c (do_inline_function_hair): Likewise. + * search.c (lookup_field_1): Likewise. + (lookup_fnfields_here): Likewise. + (lookup_field): Likewise. + (lookup_fnfields): Likewise. + (get_virtual_destructor): Likewise. + (dfs_debug_mark): Likewise. + (dfs_pushdecls): Likewise. + (dfs_compress_decls): Likewise. + * tree.c (layout_basetypes): Likewise. + * typeck.c (build_component_ref): Likewise. + (build_x_function_call): Likewise. + (build_modify_expr): Likewise. + (convert_for_initialization): Likewise. + (build_functional_cast): Likewise. + * cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Likewise. + (CTOR_NAME): New. + (DTOR_NAME): New. + * decl.c (ctor_identifier): New. + (dtor_identifier): New. + (init_decl_processing): Set them. + +Mon Mar 18 18:00:51 1996 Mike Stump + + * typeck.c (build_component_ref): Don't get confused by fields whose + context has no type name, like pointer to member functions. + +Mon Mar 18 13:19:03 1996 Jason Merrill + + * decl.c (grokdeclarator): Handle typedef without declarator. + + * pt.c (tsubst): Handle SCOPE_REF in declarator. + + * parse.y (bad_parm): Catch another case of missing `typename'. + + * lex.c (yyprint): Handle TYPE_DECLs. + + * decl.c (start_function): Don't try to be clever. + + * lex.c: Lose compiler_error_with_decl. + * typeck2.c: Lose error_with_aggr_type. + (incomplete_type_error): Use cp_* instead of old functions. + (readonly_error): Likewise. + * typeck.c (convert_arguments): Likewise. + * search.c (lookup_nested_field): Likewise. + * method.c (make_thunk): Likewise. + * decl.c (grokparms): Likewise. + * cp-tree.h: Update. + + * tree.c (min_tree_cons): Call copy_to_permanent for the purpose + and value. + +Mon Mar 18 11:25:52 1996 Bob Manson + + * method.c (build_opfncall): When deleting a pointer to an + array, build a new pointer to the tree past any ARRAY_TYPE + nodes. + +Mon Mar 18 10:11:46 1996 Brendan Kehoe + + * decl.c (lookup_name_real): Initialize local var TYPE to NULL_TREE. + +Fri Mar 15 11:03:57 1996 Jason Merrill + + * pt.c (instantiate_decl): Only call import_export_decl if at_eof + and ! DECL_INLINE. + + * decl.c (finish_function): Don't set nested based on + hack_decl_function_context. + * parse.y (function_try_block): Check for nested function. + (pending_inlines): Likewise. + + * decl2.c (build_expr_from_tree): If a unary op already has a + type, just return it. + + * decl2.c (finish_prevtable_vardecl): Use ADJUST_VTABLE_LINKAGE. + + * decl2.c (walk_vtables): vardecl_fn returns int; return 1 if it does. + (finish_file): Check the return value of walk_vtables. + (finish_prevtable_vardecl): Return int. + (finish_vtable_vardecl): Likewise. + (prune_vtable_vardecl): Likewise. + * lex.c (set_vardecl_interface_info): Likewise. + * cp-tree.h: Adjust return types. + + * class.c (delete_duplicate_fields_1): Don't complain about + duplicate nested types if they're the same type. + (finish_struct): Remove check for duplicate. + * decl2.c (grokfield): Don't check for typedef of anonymous type. + +Thu Mar 14 10:00:19 1996 Jason Merrill + + * cp-tree.h: Lose SIGNATURE_GROKKING_TYPEDEF. + + * decl.c (grokdeclarator): Lose special handling of class-level + typedef. Lose SIGNATURE_GROKKING_TYPEDEF. Set + SIGNATURE_HAS_OPAQUE_TYPEDECLS later. + + * cvt.c (convert_pointer_to_real): Retain cv-quals in conversion. + + * pt.c (tsubst_copy): Strip cv-quals from destructor name types. + + * search.c (compute_access): Fix handling of anonymous union + members. + * class.c (finish_struct_anon): Propagate TREE_{PRIVATE,PROTECTED} + from anonymous unions to their members. + + * typeck.c (build_x_function_call): For static member functions, + hand off to build_member_call. + +Wed Mar 13 14:03:34 1996 Jason Merrill + + * typeck.c (build_component_ref): Handle OFFSET_REFs. + + * init.c (expand_vec_init): Fix init == 0 case. + +Tue Mar 12 14:36:02 1996 Jason Merrill + + * init.c (build_new): pedwarn about init and array new. + (expand_vec_init): Handle lists, use convert_for_initialization. + + * typeck.c (convert_for_initialization): Pass LOOKUP_NO_CONVERSION + when converting to an aggregate type. + * cvt.c (cp_convert): Pass it through. + + * typeck.c (build_conditional_expr): Handle user-defined + conversions to slightly different types. + + * decl.c (grokdeclarator): Force an array type in a parm to be + permanent. + + * decl2.c (do_using_directive): Sorry. + (do_namespace_alias): Likewise. + * lex.c (real_yylex): Warn about using the `namespace' keyword. + +Sun Mar 10 22:26:09 1996 Jason Merrill + + * parse.y (datadef): Move call to note_list_got_semicolon up. + +Fri Mar 8 11:47:26 1996 Mike Stump + + * tree.c (unsave_expr): Don't unsave, UNSAVE_EXPRs. + +Fri Mar 8 11:29:06 1996 Mike Stump + + * decl.c (cp_finish_decl): The exception regions have to be + nested, not overlapping. We start the exception region for a + decl, after it has been fully built, and all temporaries for it + have been cleaned up. + +Thu Mar 7 17:46:06 1996 Mike Stump + + * tree.c (vec_binfo_member): Don't core dump if we have no bases. + +Thu Mar 7 14:11:49 1996 Jason Merrill + + * tree.def: Add RETURN_INIT. + * pt.c (instantiate_decl): Handle RETURN_INIT. + * decl.c (store_return_init): Handle minimal_parse_mode. + + * tree.c (cp_build_type_variant): Just return an error_mark_node. + * decl.c (make_typename_type): Don't try to get the file and line + of an identifier. + * typeck.c (comptypes): Handle TYPENAME_TYPE. + +Wed Mar 6 18:47:50 1996 Per Bothner + + * decl.c (poplevel): Make sure we clear out and restore old local + non-VAR_DECL values by default when they go out of scope. + +Wed Mar 6 09:57:36 1996 Jason Merrill + + * method.c (build_overload_value): Use DECL_ASSEMBLER_NAME in + referring to addresses of variables and functions. + + * error.c (dump_expr): Support SIZEOF_EXPR. + + * init.c (do_friend): Use the return value of check_classfn. + + * typeck.c (convert_arguments): Call complete_type. + + * method.c (hack_identifier): After giving an error, set value to + error_mark_node. + +Tue Mar 5 16:00:15 1996 Jason Merrill + + * tree.c (hack_decl_function_context): Kludge around DECL_CONTEXT + lossage for local classes. + * cp-tree.h: Declare it. + * decl.c (lookup_name_real): Evil, painful hack for local classes. + (grokfndecl): Set DECL_CLASS_CONTEXT and DECL_NO_STATIC_CHAIN here. + Use hack_decl_function_context. + (grokdeclarator): Don't set DECL_NO_STATIC_CHAIN here. + (start_function): Use hack_decl_function_context. + (finish_function): Likewise. + * method.c (synthesize_method): Likewise. + * lex.c (process_next_inline): Likewise. + (do_pending_inlines): Likewise. + * decl2.c (finish_file): Unset DECL_STATIC_FUNCTION_P when we're + done with it. + +Mon Mar 4 22:38:39 1996 Gerald Baumgartner + + * sig.c (build_signature_pointer_or_reference_type): Align + signature pointers/references on 8-byte boundaries so they can be + grabbed 2 words at a time on a Sparc. + +Tue Mar 5 10:21:01 1996 Jason Merrill + + * method.c (hack_identifier): Requiring a static chain is now a + hard error. + * decl.c (grokdeclarator): Set DECL_NO_STATIC_CHAIN on nested + functions. + +Mon Mar 4 20:03:33 1996 Jason Merrill + + * init.c (build_offset_ref): Call complete_type. + + * decl.c (pop_from_top_level): Always pop previous_class_type. + + * parse.y: Handle multiple decls in a for-init-statement. + * pt.c (tsubst_expr): Likewise. + + * pt.c (tsubst): Use tsubst_expr for the second operand of an + ARRAY_REF. + + * decl.c (maybe_push_to_top_level): Don't save previous_class_type. + (poplevel_class): Set it here. + (pop_from_top_level): Pop it here if we're returning to class scope. + * class.c (pushclass): Don't set it here. + + * decl.c (maybe_push_to_top_level): Save current_template_parms, + and clear it if !pseudo. + (pop_from_top_level): Restore it. + + * decl2.c (finish_file): Push the dummy each time we walk the list + of vtables. + + * error.c (dump_expr): Support LOOKUP_EXPR and actually do + something for CAST_EXPR. + +Mon Feb 19 14:49:18 1996 Rusty Russell + + * cvt.c (cp_convert): Warn about implicit conversion of the + address of a function to bool, as it is always true. + +Fri Feb 23 23:06:01 1996 Rusty Russell + + * typeck.c (c_expand_return): Fix warning for local externs returned. + +Mon Mar 4 15:03:11 1996 Jason Merrill + + * tree.c (mapcar): Propagate const and volatile properly. + + * typeck.c (complete_type): Be sure to instantiate the + MAIN_VARIANT of the type. + + * method.c (synthesize_method): Class interface hackery does not + apply to synthesized methods. + +Mon Mar 4 14:05:23 1996 Jason Merrill + + * pt.c (comp_template_args): Use comptypes rather than just + checking for TEMPLATE_TYPE_PARM equivalence. + + * typeck.c (build_x_function_call): Call complete_type before + checking TYPE_OVERLOADS_CALL_EXPR. + +Mon Mar 4 18:48:30 1996 Manfred Hollstein + + * g++.c (main): Check also for new define ALT_LIBM. + +Fri Mar 1 13:09:33 1996 Jason Merrill + + * pt.c (instantiate_class_template): If we don't have a pattern + yet, that's OK. + (coerce_template_parms): If we see a local class, bail. + + * decl.c (grok_reference_init): Make sure there's a type before + checking its code. + + * pt.c (do_function_instantiation): Avoid crashing on invalid decls. + (push_template_decl): Likewise. + + * parse.y (named_class_head): Set + CLASSTYPE_TEMPLATE_SPECIALIZATION here if we have basetypes. + + * decl.c (xref_tag): Diagnose redeclaration of template + type-parameter name. + + * error.c (dump_type): Handle anonymous template type parms. + + * pt.c (instantiate_template): Use TYPE_MAIN_DECL instead of + TYPE_STUB_DECL. + (coerce_template_parms): Likewise. + +Thu Feb 29 16:26:01 1996 Mike Stump + + * class.c (instantiate_type, case {ARRAY,INDIRECT}_REF, + case ADDR_EXPR): Don't modify rhs if a subinstantiation fails. + +Thu Feb 29 08:20:25 1996 Jason Merrill + + * pt.c (instantiate_template): Take the MAIN_VARIANT of the type + before trying to get its STUB_DECL. + (coerce_template_parms): Likewise. + + * parse.y (template_type_parm): If they didn't use 'class', + pretend they did after giving an error. + + * pt.c (coerce_template_parms): Diagnose use of local class. + + * decl.c (grok_reference_init): Use instantiate_type. + + * error.c (dump_expr): Handle TEMPLATE_DECLs. + + * parse.y (named_class_head): Diagnose mismatching types and tags. + + * decl.c (pushdecl): Type decls and class templates clash with + artificial type decls, not hide them. + + * decl.c (redeclaration_error_message): Diagnose redefinition of + templates properly. + (duplicate_decls): Diagnose disallowed overloads for template + functions, too. + + * decl.c (start_decl): Call complete_type before checking for a + destructor. + + * pt.c (tsubst): Use tsubst_expr on the elts of a VEC. + + * decl.c (xref_tag): A TEMPLATE_TYPE_PARM is a match. + +Wed Feb 28 09:28:44 1996 Jason Merrill + + * decl.c (grok_op_properties): Don't check for operator++(int) in + a template. + + * tree.c (perm_manip): Return a copy of variable and function + decls with external linkage. + + * tree.def: Change some of the min tree codes to type "1". + * pt.c (uses_template_parms): Handle 'e's, return 1 for LOOKUP_EXPRs. + * method.c (build_overload_int): Emit something arbitrary for + anything but an INTEGER_CST if we're in a template. + + * decl.c (cp_finish_decl): Call complete_type before deciding + whether or not to lay out the decl. + + * lex.c (do_identifier): Check for DECL_INITIAL before using it. + +Tue Feb 27 16:35:32 1996 Jason Merrill + + * typeck2.c (build_x_arrow): Call complete_type. + + * pt.c (add_pending_template): Broken out. + (lookup_template_class): If -fexternal-templates, call it for all + the methods of implemented types. + (instantiate_class_template): Instead of instantiating them here. + (instantiate_decl): Handle -fexternal-templates earlier. + +Tue Feb 27 15:51:32 1996 Brendan Kehoe + + * search.c, lex.c, decl.c, class.c, cp-tree.h: Don't wrap the + memoized lookup stuff inside GATHER_STATISTICS. + +Tue Feb 27 10:38:08 1996 Jason Merrill + + * decl.c (start_decl): Complain about array of incomplete type + here. + (grokdeclarator): Not here. + + * parse.y (template_parm): Expand full_parm inline so we can set + the rule's precedence. + + * pt.c (tsubst_expr): If we're in a template, just do tsubst_copy. + (tsubst): tsubst_expr the DECL_INITIAL of FIELD_DECLs. + * decl2.c (grokbitfield): Don't check for integer constant here. + * class.c (finish_struct_1): Check here. + + * decl.c (define_label): Make the min decl go on permanent_obstack. + + * pt.c (unify): Don't handle CONST_DECLs. + (uses_template_parms): Don't check DECL_INITIAL on a CONST_DECL. + (tsubst_copy): Likewise. + + * lex.c (do_identifier): Do pull the DECL_INITIAL out of a + CONST_DECL for a template parm. + +Mon Feb 26 12:48:18 1996 Jason Merrill + + * decl.c (grokdeclarator): Complain about array of incomplete type + here. + (start_decl_1): Not here. + + * pt.c (tsubst): Handle pointer-to-function declarators. + + * method.c (hack_identifier): If pedantic, diagnose local class + methods that require a static chain. + + * decl.c (grok_op_properties): No longer static. + * cp-tree.h: Declare it. + * pt.c (tsubst): Call it for operators. + Use tsubst_copy for TREE_VECs. + + * parse.y (template_arg): The expr has precedence like '>'. + +Fri Feb 23 14:51:52 1996 Jason Merrill + + * pt.c (coerce_template_parms): Don't coerce an expression using + template parms. + (uses_template_parms): Also check DECL_INITIAL in CONST_DECLs. + (tsubst): Don't use build_index_2_type if the max_value uses template + parms. + * method.c (build_overload_int): Emit something arbitrary for an + expression using template parms. + + * parse.y (template_close_bracket): New non-terminal to catch use + of '>>' instead of '> >' in template class names. + (template_type): Use it. + * Makefile.in (CONFLICTS): Causes one more r/r conflict. + + * tree.def: Add CAST_EXPR. + * typeck2.c (build_functional_cast): Use CAST_EXPR instead of + CONVERT_EXPR for minimal_parse_mode. + * typeck.c (build_c_cast): Likewise. + * pt.c (tsubst_copy): Likewise. + * decl2.c (build_expr_from_tree): Likewise. + * error.c (dump_expr): Likewise. + +Fri Feb 23 10:36:46 1996 Brendan Kehoe + + * except.c (SetTerminate, SetUnexpected): Put back global vars. + (init_exception_processing): Put back decl/init of + set_unexpected_fndecl and set_terminate_fndecl, needed to get the + fns from libstdc++. + + * decl.c (struct binding_level): Delete ACCEPT_ANY bitfield. + (declare_uninstantiated_type_level, uninstantiated_type_level_p): + Delete unused fns. + * cp-tree.h (declare_uninstantiated_type_level, + uninstantiated_type_level_p): Delete prototypes. + +Thu Feb 22 19:36:15 1996 Jason Merrill + + * pt.c (tsubst_expr): Add default return. + +Thu Feb 22 16:47:24 1996 Brendan Kehoe + + * error.c (fndecl_as_string): Delete unused arg CNAME. + * sig.c (build_signature_table_constructor, + build_signature_method_call): Fix calls. + + * class.c (the_null_vtable_entry): Delete var definition. + (init_class_processing): Delete tree the_null_vtable_entry init. + * decl.c (no_print_{functions, builtins}): Declare as static. + (__tp_desc_type_node): #if 0 var definition. + (init_type_desc): #if 0 init of __tp_desc_type_node. + (vb_off_identifier): Move var decl into init_decl_processing. + (current_function_assigns_this): Declare as static. + (int_ftype_ptr_ptr_int, void_ftype_ptr_int_int): Delete var decls. + (init_decl_processing): Delete init of void_ftype_ptr_ptr_int. + Move decls of string_ftype_ptr_ptr and int_ftype_string_string here. + * decl2.c (delete_sanity): Delete definition/mod of local var ELT_SIZE. + * init.c (BI_header_type, BI_header_size): Declare as static. + * pt.c (template_classes): Delete unused var. + (add_pending_template): Delete decl for non-existent fn. + (lookup_template_class): Delete vars CODE and TAG_CODE. + (instantiate_template): Delete unused var TARGS. + * cp-tree.h (vb_off_identifier, current_function_assigns_this): + Delete decls. + (__tp_desc_type_node): #if 0 var decl. + (fndecl_as_string): Fix prototype. + +Thu Feb 22 15:56:19 1996 Jason Merrill + + * tree.def: Add GOTO_STMT. + * pt.c (tsubst_expr): Support goto and labels. + * decl.c (define_label): Support minimal parsing. + * parse.y (simple_stmt): Likewise. + +Thu Feb 22 15:30:12 1996 Brendan Kehoe + + * xref.c (GNU_xref_member): Only define/set var I if + XREF_SHORT_MEMBER_NAMES is defined, to match when it's actually + used. + (GNU_xref_end_scope): Delete unused fifth arg TRNS. + (GNU_xref_end): Fix call. + * decl.c (poplevel, poplevel_class, finish_method): Fix calls. + * cp-tree.h (GNU_xref_end_scope): Fix prototype. + + * tree.c (build_exception_variant): Delete unused vars I, A, T, + T2, and CNAME. + (layout_vbasetypes): Delete unused var NONVIRTUAL_VAR_SIZE. + (mapcar): Delete unused var CODE. + (build_cplus_new): Delete unused arg WITH_CLEANUP_P. + (break_out_cleanups): Fix call. + (bot_manip): Likewise. + * call.c (build_method_call): Likewise. + * cvt.c (build_up_reference, convert_to_reference, cp_convert): + Likewise. + * typeck.c (unary_complex_lvalue, build_modify_expr, + convert_for_initialization): Likewise. + * typeck2.c (build_functional_cast): Likewise. + * cp-tree.h (build_cplus_new): Fix prototype. + + * repo.c (open_repo_file): Delete unused var Q. + (repo_compile_flags, repo_template_declared, + repo_template_defined, repo_class_defined, repo_inline_used, + repo_vtable_used, repo_tinfo_used): #if 0 unused fns. + (repo_get_id, repo_vtable_used): Declare as static. + * cp-tree.h (mark_{decl,class}_instantiated, finish_repo): Add + prototypes. + +Thu Feb 22 14:53:35 1996 Jason Merrill + + * parse.y (pending_inlines): Add function_try_block case. + + * pt.c (unify): Fix for template const parms. + +Thu Feb 22 13:24:15 1996 Brendan Kehoe + + * lex.c (extract_interface_info): Delete forward decl. + (default_copy_constructor_body, default_assign_ref_body): Delete + decls for non-existent functions. + (synth_firstobj, inline_text_firstobjs): Delete unused vars. + (init_lex): Delete setting them. + (cons_up_default_function): Delete unused vars FUNC_BUF, + FUNC_LEN, and COMPLEX. Delete code setting COMPLEX. Delete old + #if 0'd synth code. + (toplevel, expression_obstack): Delete unused extern decls. + (tree_node_kind): Delete unused enum. + (tree_node_counts, tree_node_sizes): Wrap with #ifdef + GATHER_STATISTICS. + (tree_node_kind_names): Delete unused extern decl. + (synth_obstack): Delete unused var. + (init_lex): Don't set it. + (init_parse): Add decl before use. + (reduce_count): Only define #ifdef GATHER_STATISTICS && REDUCE_LENGTH. + (current_unit_{name, language}): Delete unused vars. + (check_newline): Don't bother setting them, just accept the #pragma. + * cp-tree.h (init_repo, peek_yylex): Add prototypes. + (current_unit_{name, language}): Delete decls. + + * search.c: Wrap all of the memoized functions, macros, and + variables inside #ifdef GATHER_STATISTICS. + (lookup_field, lookup_fnfields): Likewise. + (init_search_processing): Likewise. + (reinit_search_statistics): Wrap whole function. + * lex.c (reinit_lang_specific): Wrap call to reinit_search_statistics. + + * decl.c (finish_function): Only call pop_memoized_context if + GATHER_STATISTICS is defined. + (start_function): Likewise for push_memoized_context. + * class.c (pushclass, popclass): Likewise. + + * cp-tree.h (CLASSTYPE_MTABLE_ENTRY): Move definition from here... + * search.c (CLASSTYPE_MTABLE_ENTRY): ... to here. + + * cvt.c (cp_convert): Delete unused local var FORM. + * cp-tree.h (can_convert, can_convert_arg, real_lvalue_p): Add + prototypes. + +Thu Feb 22 13:19:44 1996 Jason Merrill + + * pt.c (do_poplevel): Oops; really return what we get from + poplevel this time. + +Thu Feb 22 11:41:44 1996 Brendan Kehoe + + * cp-tree.h (is_aggr_type): Add prototype. + + * cp-tree.h ({push,pop}_cp_function_context): Add decls. + * method.c ({push,pop}_cp_function_context): Delete decls. + * except.c (start_eh_unwinder, end_eh_unwinder): Declare as void. + (SetUnexpected, SetTerminate): Delete unused vars. + (init_exception_processing): Don't set SetUnexpected or + SetTerminate. Don't set SET_UNEXPECTED_FNDECL or SET_TERMINATE_FNDECL. + (output_exception_table_entry): Delete unused array LABEL. + (expand_internal_throw): Delete unused var PARAMS. + (expand_start_catch_block): Delete unused var CLEANUP. + (emit_exception_table): Delete unused var EH_NODE_DECL. + (expand_builtin_throw): Delete unused vars UNWIND_AND_THROW and + GOTO_UNWIND_AND_THROW. Don't set them. + (end_eh_unwinder): Add top decl. + (pop_rtl_from_perm): Delete unused decl of PERMANENT_OBSTACK. + (exception_section, push_rtl_perm, do_function_call, + lang_interim_eh, push_eh_cleanup, eh_outer_context, + expand_end_eh_spec, end_eh_unwinder): Declare as static. + (saved_pc, saved_throw_type, saved_throw_value, saved_cleanup, + throw_used): Likewise. + * cp-tree.h (expand_end_eh_spec): Delete prototype. + + * search.c (dfs_mark, dfs_mark_vtable_path, + dfs_unmark_vtable_path, dfs_mark_new_vtable, + dfs_unmark_new_vtable, dfs_clear_search_slot, + dfs_search_slot_nonempty_p, bfs_markedp, bfs_unmarkedp, + bfs_marked_vtable_pathp, bfs_unmarked_vtable_pathp, + bfs_marked_new_vtablep, bfs_unmarked_new_vtablep): #if 0 unused + functions. + (n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1, + n_calls_lookup_fnfields, n_calls_lookup_fnfields_1, + n_calls_get_base_type, n_outer_fields_searched, n_contexts_saved): + Only define #ifdef GATHER_STATISTICS. + (reinit_search_statistics): Only init some vars if GATHER_STATISTICS + is defined. + (vbase_decl): Delete var definition. + (init_search): Delete old decl. + (init_vbase_pointers): Delete building of VBASE_DECL, since it's + never actually used. + (expand_indirect_vtbls_init): Delete init of VBASE_DECL. + (get_base_distance_recursive): Delete unused fourth arg + BASETYPE_PATH. Fix call . + (get_base_distance): Fix call. + (push_class_decls): Delete unused var ID. + (make_memoized_table_entry): Declare as static. + (breadth_first_search): Declare as static. + (tree_has_any_destructor_p): Declare as static. + (pop_class_decls): Delete unused arg pop_class_decls. + * class.c (popclass): Fix call to pop_class_decls. + * cp-tree.h (make_memoized_table_entry, breadth_first_search, + tree_has_any_destructor_p): Delete prototypes. + + * rtti.c (build_ptmf_desc): Delete unused arg TYPE. + (build_t_desc): Fix call. Delete unused vars ELEMS and TT. + (build_dynamic_cast): Delete unused local vars TMP1 and RETVAL. + (build_user_desc): Delete unused var T. + (build_class_desc): Delete unused vars T and OFF. + (build_t_desc): Delete unused var NAME_STRING. + (build_headof): Make static. + (get_bad_cast_node): Likewise. + (get_def_to_follow): Likewise. + * cp-tree.h (init_type_desc): Add prototype. + (build_headof): Remove prototype. + +Thu Feb 22 00:54:22 1996 Jason Merrill + + * pt.c (tsubst): Only look for matching decls at file scope for + non-member functions. + + * call.c (build_scoped_method_call): Handle scoped destructor + calls in templates. + + * decl.c (*_top_level): Also save previous_class_values. + + * pt.c (tsubst_expr): Support do {} while loops. + * parse.y (simple_stmt): Likewise. + * tree.def: Likewise. + + * method.c (build_overload_identifier): For a class nested in a + template class, don't mangle in the template parms from our + context. + + * lex.c, cp-tree.h: Remove support for template instantiations in + the pending_inlines code. + * pt.c: Remove dead functions and unused arguments. + (uses_template_parms): TYPENAME_TYPEs always use template parms. + * parse.y: Stop passing anything to end_template_decl. + * tree.c (print_lang_statistics): Only print tinst info #ifdef + GATHER_STATISTICS. + +Wed Feb 21 16:57:33 1996 Brendan Kehoe + + * init.c (expand_recursive_init{,_1}): Delete decls. + (sort_member_init): Delete unused var INIT. + (emit_base_init): Delete unused var X. + (build_offset_ref): Delete unused var CNAME. + (sort_member_init): Delete unused var FIELDS_TO_UNMARK. + (emit_base_init): Delete unused local var BASE. Delete extern + decl of IN_CHARGE_IDENTIFIER. + (build_delete): Delete unused local var VIRTUAL_SIZE. + + * init.c (build_vec_delete): Delete unused third arg ELT_SIZE. + (build_delete): Fix call. + * decl2.c (delete_sanity): Likewise. + * cp-tree.h (build_vec_delete): Update prototype. + + * typeck.c (common_base_type): Delete unused var TMP. + (build_binary_op): Delete local var ARGS_SAVE. + (build_array_ref): Delete unused var ITYPE. + (c_expand_return): Delete unused var USE_TEMP. + + * typeck.c (compexcepttypes): Delete unused arg STRICT. + (comptypes): Fix calls. + * decl.c (duplicate_decls): Likewise. + * cp-tree.h (compexcepttypes): Delete extra arg. + + * decl2.c (check_classfn): Delete unused second arg CNAME. + * decl.c (start_decl, grokfndecl): Fix calls. + * init.c (do_friend): Likewise. + * cp-tree.h (check_classfn): Update prototype. + + * cp-tree.h (signature_error, import_export_vtable, + append_signature_fields, id_in_current_class, mark_used, + copy_assignment_arg_p): Add decls. + * decl2.c (mark_used): Delete decl. + + * class.c (n_*): Wrap with #ifdef GATHER_STATISTICS. + + * class.c (get_vtable_entry): Disable unused function. + (doing_hard_virtuals): Delete unused static global var. + (finish_struct_1): Don't init DOING_HARD_VIRTUALS. + (prepare_fresh_vtable): Delete unused vars PATH and RESULT. + (overrides): Delete unused vars RETTYPE and BASE_RETTYPE. + (modify_one_vtable): Delete unused var OLD_RTTI. + (finish_struct_anon): Delete unused vars OFFSET and X. + (finish_struct_bits): Delete unused var METHOD_VEC. + (get_basefndecls): Delete unused var PURPOSE. Delete unused + for-scope local variable METHODS. + + * call.c (user_harshness): Delete unused/unneeded arg PARM. + (ideal_candidate): Delete unused args BASETYPE and PARMS. + (build_method_call): Delete unused args passed into ideal_candidate. + (build_overload_call_real): Likewise. Delete unused var OVERLOAD_NAME. + * cp-tree.h (synthesize_method): Add decl. + + * decl.c (note_level_for_for): Give void return type. + (pushdecl_nonclass_level): Likewise. + (finish_function): Delete unused vars VFIELDS and ALLOCATED_THIS. + (poplevel): Delete unused var IMPLICIT_TRY_BLOCK. + (suspend_binding_level): Delete unused var LEVEL. + (duplicate_decls): Delete unused var CTYPE. + (duplicate_decls): Delete unused var PREVIOUS_C_DECL. + (init_decl_processing): Delete unused vars FLOAT_ENDLINK and + PTR_ENDLINK. + (grokdeclarator): Delete unused var C. + (grokdeclarator): Delete unused var SIZE_VARIES. + (grokparms): Delete unused var SAW_VOID. + (start_function): Delete unused var OLDDECL. + (cplus_expand_expr_stmt): Delete unused var + REMOVE_IMPLICIT_IMMEDIATELY. + + * cp-tree.h (pushdecl_nonclass_level): Fix prototype. + + * Makefile.in (CONFLICTS): Update to 12 shift/reduce. + +Wed Feb 21 00:06:17 1996 Jason Merrill + + * tree.c (build_min): Set TREE_COMPLEXITY to lineno. + (build_min_nt): Likewise. + * pt.c (do_pushlevel): Emit line note. + (do_poplevel): Return what we get from poplevel. + (tsubst_expr): Set lineno from TREE_COMPLEXITY in stmt nodes. + * parse.y: Use do_pushlevel and do_poplevel. + * cp-tree.h: Declare do_poplevel. + + * cp-tree.h: Declare at_eof. + * decl.c (cp_finish_decl): Pass it to rest_of_decl_compilation. + * decl2.c (import_export_decl): Renamed from import_export_inline. + (finish_file): Call it to do interface handling for statics. + * pt.c (tsubst_copy): Call mark_used on variables and functions + used here. + + * decl2.c (finish_file): Don't emit statics we can't generate. + * pt.c (instantiate_decl): Don't set interface on instantiations + we can't generate. + + * cp-tree.h (struct tinst_level): Change 'classname' to 'decl'. + * tree.c (print_lang_statistics): Print max template depth. + * pt.c (push_tinst_level): Dump entire instantiation context. + (instantiate_class_template): Use it and pop_tinst_level. + (instantiate_decl): Likewise. + + * call.c class.c cp-tree.h decl.c decl2.c error.c lex.c method.c + pt.c ptree.c tree.def: Remove all traces of UNINSTANTIATED_P_TYPE. + +Tue Feb 20 18:21:51 1996 Jason Merrill + + * call.c class.c cp-tree.h cvt.c decl.c decl2.c error.c expr.c + init.c lex.c method.c parse.y pt.c repo.c search.c spew.c tree.c + tree.def typeck.c typeck2.c xref.c: Massive, systemic changes for + the new template implementation. + +Tue Feb 20 17:14:29 1996 Brendan Kehoe + + * decl2.c (check_cp_case_value): Use STRIP_TYPE_NOPS. + +Thu Feb 15 18:44:42 1996 Mike Stump + + * decl.c (cp_finish_decl): Delay emitting the debug information for + a typedef that has been installed as the canonical typedef, if the + type has not yet been defined. + +Thu Feb 15 09:39:08 1996 Jason Merrill + + * decl2.c (grokfield): Still call pop_nested_class for access decls. + +Wed Feb 14 17:30:04 1996 Brendan Kehoe + + * decl.c (lookup_label): Call label_rtx. + + * decl.c (make_binding_level): New function. + (pushlevel, pushlevel_class): Call it instead of explicit + duplicate calls to xmalloc. + + * decl.c (init_decl_processing): Delete useless build_pointer_type + call. + + * decl.c (float_ftype_float, ldouble_ftype_ldouble): Add definitions. + (sizet_ftype_string): Delete variable. + (init_decl_processing): Add built-in functions fabsf, fabsl, + sqrtf, sqrtl, sinf, sin, sinl, cosf, cos, cosl. New local + variable strlen_ftype, used for strlen. + +Wed Feb 14 16:21:25 1996 Jason Merrill + + * decl.c (push_to_top_level): Start from current_binding_level + again for now; the stl hacks depend on g++ being broken in this + way, and it'll be fixed in the template rewrite. + + * tree.def: Add USING_DECL. + * decl2.c (do_class_using_decl): Implement. + (grokfield): Pass access decls off to do_class_using_decl instead of + grokdeclarator. + * error.c (dump_decl): Handle USING_DECLs. + * decl.c (grokdeclarator): Remove code for handling access decls. + * class.c (finish_struct_1): Adjust accordingly, treat using-decls + as access decls for now. + (finish_struct): Don't check USING_DECLs for other uses of the name. + + * search.c (get_matching_virtual): Use cp_error_at. + +Wed Feb 14 10:36:58 1996 Brendan Kehoe + + * typeck.c (comptypes): Default COMP_TYPE_ATTRIBUTES to 1, to + match c-typeck.c. + (self_promoting_args_p): Move the check that TYPE is non-nil + before trying to look at its main variant. + (unsigned_type, signed_type): Add checking of DI/SI/HI/QI nodes. + + * cp-tree.h (DECL_WAITING_FRIENDS, SET_DECL_WAITING_FRIENDS): + Delete macros. + * init.c (xref_friend, embrace_waiting_friends): Delete functions. + (do_friend): Delete call to xref_friend. + * class.c (finish_struct_1): Delete call to embrace_waiting_friends. + + * typeck.c (convert_sequence): #if 0 unused function. + + * cp-tree.h (DECL_IN_MEMORY_P): New macro w/ the check that used to + be in decl_in_memory_p. + (decl_in_memory_p): Delete decl. + * expr.c (decl_in_memory_p): Delete fn. + * typeck.c (mark_addressable): Use DECL_IN_MEMORY_P. + + * decl.c (cp_finish_decl): Use DECL_IN_MEMORY_P. + +Tue Feb 13 12:51:21 1996 Jason Merrill + + * class.c (finish_struct_1): Check for a pure-specifier on a + non-virtual function here. + + * decl2.c (grok_function_init): Don't check whether the function + is virtual here. + (grokfield): Don't call check_for_override here. + + * decl.c (push_to_top_level): Start from inner_binding_level, + check class_shadowed in class levels. + +Mon Feb 12 17:46:59 1996 Mike Stump + + * decl.c (resume_level): Ignore things that don't have names, instead + of core dumping. + +Mon Feb 12 15:47:44 1996 Brendan Kehoe + + * decl2.c (grokfield): Set DECL_VINDEX properly for FUNCTION_DECLs. + +Sat Feb 10 17:59:45 1996 Jason Merrill + + * class.c (finish_struct_1): Set DECL_VINDEX properly on a + synthesized dtor. + + * parse.y (complete_type_name): Bind global_scope earlier. + (complex_type_name): Likewise. + (qualified_type_name): Remove. + +Thu Feb 8 15:15:14 1996 Jason Merrill + + * decl.c (grokfndecl): Move code that looks for virtuals in base + classes... + * class.c (check_for_override): ... to a new function. + (finish_struct_1): Call it. + + * cp-tree.h: Declare warn_sign_compare. + + * typeck.c (build_binary_op_nodefault): Check warn_sign_compare + rather than extra_warnings to decide whether to warn about + comparison of signed and unsigned. + + * decl2.c (lang_decode_option): Handle warn_sign_compare. -Wall + implies -Wsign-compare. -Wall doesn't imply -W. + +Wed Feb 7 15:27:57 1996 Mike Stump + + * typeck.c (build_component_ref): Fix to handle anon unions in base + classes as well. + +Wed Feb 7 14:29:12 1996 Brendan Kehoe + + * class.c (resolves_to_fixed_type_p): Delete code dealing with + a WITH_CLEANUP_EXPR, since we don't generate them any more. + * cvt.c (build_up_reference): Likewise. + * decl.c (grok_reference_init): Likewise. + (cp_finish_decl): Likewise. + * error.c (dump_expr): Likewise. + * tree.c (real_lvalue_p): Likewise. + (lvalue_p): Likewise. + (build_cplus_new): Likewise. + (unsave_expr_now): Likewise. + * typeck.c (unary_complex_lvalue, build_modify_expr, + c_expand_return): Likewise. + +Tue Feb 6 13:39:22 1996 Brendan Kehoe + + Make the C++ front-end pay attention to attributes for structures. + * class.c (finish_struct): New argument ATTRIBUTES, passed down into + finish_struct_1. + (finish_struct_1): New argument ATTRIBUTES; call cplus_decl_attributes. + Take out old round_up_size use and setting the DECL_ALIGN possibly + using it. Take out setting of TYPE_ALIGN to round_up_size, which + can override what the attribute set. + * cp-tree.h (finish_struct): Update prototype. + * parse.y (template_instantiate_once): Pass a NULL_TREE for the + attributes to finish_struct. + (structsp): For a CLASS decl, add maybe_attribute to rule and pass that + value down into finish_struct. + * Makefile.in (CONFLICTS): Switch to 7 shift/reduce conflicts. + +Tue Feb 6 13:12:15 1996 Per Bothner + + * decl.c (poplevel): Re-word dead for local handling. + (pushdecl): Remove useless DECL_DEAD_FOR_LOCAL test. + (cp_finish_decl): If is_for_scope, check for duplicates so + we can disable is_for_scope. Otherwise, preserve_temp_slots. + + * lex.c (do_identifier): Use global binding in preference of + dead for local variable. + +Mon Feb 5 17:46:46 1996 Mike Stump + + * init.c (initializing_context): Handle anon union changes, the + context where fields of anon unions can be initialized now has to be + found by walking up the TYPE_CONTEXT chain. + +Fri Feb 2 14:54:04 1996 Doug Evans + + * decl.c (start_decl): #ifdef out code to set DECL_COMMON + if ASM_OUTPUT{,_ALIGNED}_BSS is defined. + (obscure_complex_init): If bss is supported, always set + DECL_INITIAL to error_mark_node. + +Thu Feb 1 16:19:56 1996 Brendan Kehoe + + * init.c (is_friend): Make sure there's a context before we see if + it's an aggr type. + +Thu Feb 1 15:44:53 1996 Mike Stump + + * init.c (is_friend): Classes are not friendly with nested classes. + +Thu Feb 1 15:27:37 1996 Doug Evans + + * lex.c (check_newline): Pass last character read to HANDLE_PRAGMA, + and record its result. + +Thu Feb 1 09:27:01 1996 Mike Stump + + * class.c (finish_struct_anon): Switch around code to not move anon + union elements around, nor mess up their contexts, nor offsets, + instead we now build up the right number of COMPONENT_REFs for all + the anon unions that may be present at build_component_ref time. + * typeck.c (lookup_anon_field): New routine to handle field lookup + on fields without names. We find them, based upon their unique type + instead. + * typeck.c (build_component_ref): Allow FIELD_DECL components. + Handle finding components in anonymous unions, and ensure that a + COMPONENT_REF is built for each level as necessary. + +Tue Jan 30 18:18:23 1996 Mike Stump + + * cvt.c (build_up_reference): Make the INDIRECT_BIND case come after + code that ensures that copy ctors are used if appropriate. + +Tue Jan 30 17:35:14 1996 Brendan Kehoe + + * init.c (build_vec_delete): Only give an error if base isn't an + error_mark_node. + +Mon Jan 29 17:09:06 1996 Mike Stump + + * spew.c (do_aggr): `new struct S;' isn't a forward declaration. + (yylex): If we see `new', keep slurping. + +Thu Jan 25 18:31:36 1996 Mike Stump + + * class.c (finish_struct_1): Move code for handling anon unions... + (finish_struct_anon): to here. Fixup so that we do the offset + calculations right, and so that the fields are physically moved to + the containers's chain. + +Thu Jan 25 18:27:37 1996 Brendan Kehoe + + * decl.c (grokdeclarator): Avoid trying to get an operand off an + identifier node. + +Wed Jan 24 11:25:30 1996 Jim Wilson + + * typeck.c (pointer_int_sum): Use TYPE_PRECISION (sizetype) not + POINTER_SIZE to agree with expr.c. + +Thu Jan 25 13:01:23 1996 Mike Stump + + * search.c (lookup_field): Don't report ambiguities if protect is 0, + instead return NULL_TREE. + +Wed Jan 24 13:01:26 1996 Mike Stump + + * class.c (finish_struct_1): Call warn_hidden if we want warnings + about overloaded virtual functions. + (warn_hidden): New routine to warn of virtual functions that are + hidden by other virtual functions, that are not overridden. + (get_basefndecls): New routine, used by warn_hidden. + (mark_overriders): New routine, used by warn_hidden. + * search.c (get_matching_virtual): Remove old warning that just + isn't very useful. + +Tue Jan 23 12:26:10 1996 Brendan Kehoe + + * decl.c (output_builtin_tdesc_entries): #if 0 the function definition. + + * typeck.c (null_ptr_cst_p): Delete unused fn. + (build_function_call_maybe): Delete unused fn. + + * expr.c (extract_init): #if 0 the code after unconditional return 0 + for now. + + Delete old cadillac code. + * edsel.c: Remove file. + * Make-lang.in (CXX_SRCS): Take edsel.c off the list. + * Makefile.in (CXX_OBJS): Delete edsel.o. + (edsel.o): Delete rule. + * cp-tree.h (flag_cadillac): Delete var decl. + * lang-options.h: Delete "-fcadillac" and "-fno-cadillac". + * decl2.c (flag_cadillac): Delete var definition. + (lang_decode_option): Delete handling of -fcadillac and -fno-cadillac. + (grokfield): Delete code depending on flag_cadillac. + (finish_anon_union): Likewise. + * class.c (finish_struct_1): Likewise. + (pushclass): Likewise. + (popclass): Likewise. + (push_lang_context): Likewise. + (pop_lang_context): Likewise. + * decl.c (init_decl_processing): Likewise. + (start_decl): Likewise. + (cp_finish_decl): Likewise. + (xref_tag): Likewise. + (finish_enum): Likewise. + (start_function): Likewise. + (finish_function): Likewise. + (finish_stmt): Likewise. + * lex.c (lang_init): Likewise. + (check_newline): Likewise. + + * lex.c (do_pending_inlines): Delete synthesized method kludge. + + Delete defunct, ancient garbage collection implementation. + * rtti.c: New file with the RTTI stuff from gc.c. + * gc.c: Removed file (moved the remaining stuff into rtti.c). + * Makefile.in (CXX_OBJS): Replace gc.o with rtti.o. + (rtti.o): New rule, replacing gc.o. + * Make-lang.in (CXX_SRCS): Replace gc.c with rtti.c. + * cp-tree.h: Delete gc-related fn decls. + (DECL_GC_OFFSET): Delete macro. + (flag_gc): Delete extern decl. + * decl.c (current_function_obstack_index): Delete var decl. + (current_function_obstack_usage): Delete var decl. + (start_function): Delete clearing of current_function_obstack_index + and current_function_obstack_usage. + (init_decl_processing): Delete code relying on -fgc. + Delete call to init_gc_processing. + (cp_finish_decl): Delete calls to build_static_gc_entry and + type_needs_gc_entry. Delete gc code setting DECL_GC_OFFSET. + (store_parm_decls): Delete -fgc calls to cp_expand_decl_cleanup + and to expand_expr of a __gc_main call. + (maybe_gc_cleanup): Delete var decl. + (finish_function): Delete call to expand_gc_prologue_and_epilogue. + * decl2.c (flag_gc): Delete var decl. + (lang_f_options): Delete offering of -fgc. + (lang_decode_option): Delete -fgc and -fno-gc handling. + (get_temp_regvar): Delete gc code. + * init.c (build_new): Delete gc code. + * lex.c (init_lex): Delete checking of flag_gc. + + * typeck.c (convert_arguments): Delete gc code. + (build_component_addr): Delete -fgc warning. + (build_modify_expr): Delete gc code. + + * decl2.c (build_push_scope): Delete fn. + * cp-tree.h (build_push_scope): Delete decl. + + * search.c (clear_search_slots): Delete fn. + * cp-tree.h (clear_search_slots): Delete decl. + + * search.c (tree_needs_constructor_p): Delete fn. + * cp-tree.h (tree_needs_constructor_p): Delete decl. + + * tree.c (id_cmp): Delete fn. + + * tree.c (set_fnaddr_from_vtable_entry): Delete fn. + * cp-tree.h (set_fnaddr_from_vtable_entry): Delete decl. + + * tree.c (decl_value_member): Delete fn. + * cp-tree.h (decl_value_member): Delete decl. + + * tree.c (list_hash_lookup_or_cons): Delete fn. + * cp-tree.h (list_hash_lookup_or_cons): Delete decl. + + * method.c (cplus_exception_name): Delete fn. + (EXCEPTION_NAME_{PREFIX, LENGTH}): Delete macros. + + * spew.c (shift_tokens): Delete fn. + +Mon Jan 22 17:49:33 1996 Jason Merrill + + * except.c (init_exception_processing): Pass 1 to needs_pop in calls + to cp_finish_decl. + * parse.y: Likewise. + +Mon Jan 22 17:34:29 1996 Brendan Kehoe + + * tree.c (build_cplus_staticfn_type): Delete function definition; + never used. + * cp-tree.h (build_cplus_staticfn_type): Delete decl. + + * tree.c (virtual_member): Delete function definition; never used. + * cp-tree.h (virtual_member): Delete decl. + +Fri Jan 19 18:03:14 1996 Mike Stump + + * typeck.c (build_component_ref): Handle getting vbase pointers + out of complex multiple inheritance better. + +Fri Jan 19 16:27:40 1996 Mike Stump + + * typeck.c (build_object_ref): Make sure we use the real type, not + any reference type. + +Fri Jan 19 16:01:47 1996 Mike Stump + + * tree.c (build_exception_variant): Don't create new types if we + don't have to, also build new types on the right obstack. + +Fri Jan 19 14:09:44 1996 Jason Merrill + + * decl.c (store_bindings): Split out from push_to_top_level. + (push_to_top_level): Call it for b->type_shadowed on class binding + levels. + +Fri Jan 19 13:53:14 1996 Mike Stump + + * search.c (expand_upcast_fixups): Fix so that offsets stored in + vbase_offsets are always right. Fixes a problem where virtual base + upcasting and downcasting could be wrong during conversions on this + during virtual function dispatch at ctor/dtor time when dynamic + vtable fixups for deltas are needed. This only sounds easier than + it is. :-) + (fixup_virtual_upcast_offsets): Change to reflect new calling + convention for expand_upcast_fixups. + +Fri Jan 19 12:23:08 1996 Brendan Kehoe + + * decl2.c (grokbitfield): Strip the NOPs from WIDTH before we + check that it's usable as the bitfield width. + +Wed Jan 17 21:22:40 1996 Brendan Kehoe + + * decl2.c (grokfield): Call cplus_decl_attributes with the attrlist. + Pass a null tree to grokdeclarator for its ATTRLIST arg, since it's + only ever used for functions in it. + +Wed Jan 17 12:10:38 1996 Jason Merrill + + * parse.y (qualified_type_name): Use the TYPE_DECL, not the type. + (nested_type): Likewise. + (nested_name_specifier): Use lastiddecl. + + * decl.c (grokdeclarator): Adjust accordingly. + * init.c (expand_member_init): Likewise. + * parse.y (base_class): Likewise. + * typeck2.c (build_functional_cast): Likewise. + + * typeck2.c (build_functional_cast): Fill in name after we've + checked for non-aggr type. + +Wed Jan 17 10:18:01 1996 Mike Stump + + * decl2.c (warn_pointer_arith): Default to on. + +Tue Jan 16 12:45:38 1996 Jason Merrill + + * lex.c (is_rid): New function. + * decl.c (grokdeclarator): Diagnose reserved words used as + declarator-ids. + +Tue Jan 16 11:39:40 1996 Jason Merrill + + * tree.c (get_decl_list): Don't lose cv-quals. + + * decl.c (grokdeclarator): Fix SCOPE_REF handling and diagnose + typespecs used as declarator-ids. + +Tue Jan 16 11:09:42 1996 Mike Stump + + * decl.c (poplevel): When poping a level, don't give a warning for + any subblocks that already exist. + +Tue Jan 16 00:25:33 1996 Jason Merrill + + * typeck.c (build_object_ref): Finish what I started. + + * parse.y (qualified_type_name): Don't check TYPE_BUILT_IN. + + * decl2.c (constructor_name_full): Handle TEMPLATE_TYPE_PARMs. + + * decl.c (grokdeclarator): Also accept TEMPLATE_TYPE_PARM as a + scope. + +Mon Jan 15 16:19:32 1996 Jason Merrill + + * decl.c (xref_tag): Handle passing a type in directly. + + * parse.y (qualified_type_name): Pull out the type. + (nested_type): Likewise. + Take types directly instead of as identifiers. + * call.c (build_scoped_method_call): Take types directly instead of + as identifiers. + * decl.c (xref_basetypes): Likewise. + * init.c (expand_member_init): Likewise. + (build_member_call): Likewise. + (build_offset_ref): Likewise. + * typeck2.c (build_scoped_ref): Likewise, remove bogus code. + * method.c (do_build_assign_ref): Likewise. + * decl.c (grokdeclarator): Handle a type appearing as the + declarator-id for constructors. + * method.c (do_build_copy_constructor): current_base_init_list now + uses the types directly, not their names. + * init.c (sort_base_init): Likewise. + (expand_member_init): Likewise. + * init.c (is_aggr_type): New function, like is_aggr_typedef. + +Mon Jan 15 08:45:01 1996 Jeffrey A Law + + * tree.c (layout_basetypes): Call build_lang_field_decl instead + of build_lang_decl if first arg is a FIELD_DECL. + +Thu Jan 11 14:55:07 1996 Brendan Kehoe + + * decl.c (cp_finish_decl): Only clear TREE_USED if DECL_NAME is + non-empty. + * except.c (expand_start_catch_block): Set TREE_USED to avoid + warnings about the catch handler. + +Mon Jan 8 17:35:12 1996 Jason Merrill + + * typeck.c (build_modify_expr): Use a COMPOUND_EXPR instead of + expand_target_expr. + +Thu Jan 4 12:30:32 1996 Brendan Kehoe + + Fix access control to use trees rather than integers. + * class.c (access_{default, public, protected, private, + default_virtual, public_virtual, private_virtual}_node): Add + definitions. + (init_class_processing): Do creation of those nodes. + * cp-tree.h (access_type): Delete enum decl. + (access_{default, public, protected, private, default_virtual, + public_virtual, private_virtual}_node): Add decls. + (compute_access): Change return type. + * search.c (compute_access): Have tree return type, instead of enum. + (lookup_field): Declare THIS_V and NEW_V to be tree nodes. + * lex.c (real_yylex): Use yylval.ttype for giving the value of the + access_* node for each of RID_{PUBLIC, PRIVATE, PROTECTED}. + * parse.y (VISSPEC): Make ttype rather than itype. + (base_class_access_list): Likewise. + * *.[cy]: Change all refs of `access_public' to `access_public_node', + etc. + * call.c (build_method_call): Make ACCESS be a tree. + * class.c (alter_access, finish_struct_1, filter_struct): Likewise. + * cvt.c (convert_to_aggr): Likewise. + * init.c (build_offset_ref, resolve_offset_ref, build_delete): + Likewise. + * method.c (hack_identifier): Likewise. + * typeck.c (build_component_ref_1, build_component_ref): ): Likewise. + +Thu Jan 4 11:02:20 1996 Mike Stump + + * typeck.c (pointer_int_sum, pointer_diff): Make code agree with C + frontend, and make it more consistent with respect to + warn_pointer_arith. + +Tue Jan 2 00:13:38 1996 Rusty Russell + + * decl.c (pushdecl): Check for duplicate parameter names. + +Wed Jan 3 09:25:48 1996 Mike Stump + + * decl.c (expand_static_init): Call assemble_external for atexit. + +Wed Jan 3 07:55:19 1996 Mike Stump + + * except.c (do_unwind): Remove some generated dead code. + (eh_outer_context): New routine, factor out some common code from + expand_builtin_throw and end_eh_unwinder. Add code to do return + address masking for the PA. + (expand_builtin_throw): Use eh_outer_context instead of open coding + it here. + (end_eh_unwinder): Likewise. + +Tue Jan 2 17:00:56 1996 Mike Stump + + * except.c (expand_throw): Call assemble_external for __empty, if we + use it. + +Thu Dec 28 11:13:15 1995 Mike Stump + + * except.c (expand_builtin_throw): Use RETURN_ADDR_OFFSET instead of + NORMAL_RETURN_ADDR_OFFSET. + (end_eh_unwinder): Likewise. + +Wed Dec 27 22:18:16 1995 Mike Stump + + * gc.c (build_dynamic_cast): Make sure we don't cast away const + when dealing with references, and make sure we handle dynamic + casting to a cv qualified reference. + +Thu Dec 21 23:50:35 1995 Mike Stump + + * except.c (struct eh_context): New structure top hold eh context + information. + (push_eh_context): New routine. + (pop_eh_context): Likewise. + * decl.c (push_cp_function_context): Use them. + (pop_cp_function_context): Likewise. + +Wed Dec 20 12:42:51 1995 Jason Merrill + + * decl2.c (finish_file): Also prune uninteresting functions in the + inline emission loop. + +Wed Dec 20 02:32:07 1995 Jeffrey A Law + + * sig.c (build_signature_table_constructor): Mark functions + in the signature as referenced. + +Tue Dec 19 22:36:56 1995 Jason Merrill + + * decl2.c (finish_file): Do all the vtable/synthesis stuff before + the inline emission stuff. + +Mon Dec 18 15:51:33 1995 Jason Merrill + + * cp-tree.h, decl2.c (flag_weak): New flag to control the use of + weak symbols. + * lang-options.h: Add -f{no-,}weak. + * decl.c (init_decl_processing): If the target does not support weak + symbols, don't use them. + * decl2.c, pt.c: s/SUPPORTS_WEAK/flag_weak/. + +Sun Dec 17 21:13:23 1995 Rusty Russell + + * init.c (expand_member_init): warning for base init after members. + +Fri Dec 15 15:32:18 1995 Jason Merrill + + * cvt.c (build_expr_type_conversion): Don't convert to a reference + type. + +Thu Dec 14 16:05:58 1995 Mike Stump + + * method.c (report_type_mismatch): Improve wording for volatile + mismatches. + +Thu Dec 14 14:16:26 1995 Mike Stump + + * init.c (expand_aggr_init_1): Use expand_aggr_init_1 instead of + expand_assignment, as the later doesn't handle things that have + copy constructors well. The compiler would do bitwise copying, + instead of ctor calling in some cases. + +Wed Dec 13 17:05:54 1995 Paul Eggert + + * g++.c (my_strerror): Return "cannot access" if errno is 0. + (pfatal_with_name, perror_exec): Don't assume that + the returned value from my_strerror contains no '%'s. + (concat): Remove. + (sys_nerror): Declare only if HAVE_STRERROR is not defined. + +Wed Dec 13 16:22:38 1995 Jason Merrill + + Lose CLASSTYPE_METHODS/DECL_NEXT_METHOD chain; make + TYPE_METHODS/TREE_CHAIN mean what they used to. + * decl2.c (constructor_name_full): Refer to CLASSTYPE_METHOD_VEC + instead of TYPE_METHODS. + * decl.c (duplicate_decls): Lose references to DECL_NEXT_METHOD. + * tree.c (tree_copy_lang_decl_for_deferred_output): Likewise. + * cp-tree.h (CLASSTYPE_METHODS): Lose. + (CLASSTYPE_METHOD_VEC): Point to lang_spec->methods instead of + TYPE_METHODS. + (struct lang_decl): Lose next_method field. + (DECL_NEXT_METHOD): Lose. + * class.c (finish_struct_methods): Don't mess with TYPE_METHODS. + (finish_struct): Just use TYPE_METHODS; we don't need fn_fields + anymore. + (finish_struct_methods): Don't mess with the TREE_CHAINs in + fn_fields. + + * search.c (add_conversions): Don't use TREE_CHAIN to traverse method + vector. + + * call.c (build_method_call): Synthesize here even when not inlining. + * typeck.c (build_function_call_real): Likewise. + +Wed Dec 13 15:02:39 1995 Ian Lance Taylor + + * cp/lex.c (check_newline): If DBX_DEBUGGING_INFO and write_symbols + == DBX_DEBUG, call dbxout_start_new_source_file and + dbxout_resume_previous_source_file when appropriate. + +Tue Dec 12 20:38:55 1995 Mike Stump + + * except.c (start_anon_func): Push to the top level. + (end_anon_func): Pop from the top level. + +Mon Dec 11 18:56:14 1995 Mike Stump + + * cp-tree.h (build_cleanup): New routine to build cleanups. + * decl.c (expand_static_init): Use build_cleanup to build a cleanup + call at ctor time and use atexit to run it later. + * decl2.c (build_cleanup): New routine, taken from finish_file. + (finish_file): Use build_cleanup instead, and don't put function + local statics in global dtor list. + +Wed Dec 6 14:34:29 1995 Mike Stump + + * except.c (expand_throw): Ensure that we have cleanups, if we try + and expand cleanups. + +Wed Dec 6 11:48:21 1995 Mike Stump + + * except.c (expand_throw): Add logic to manage dynamic cleanups for + the EH object. + (expand_end_catch_block): Use the magic of expand_goto, instead of + emit_jump so that we get the cleanup for any catch clause parameter + and the cleanup for the exception object. Update to reflect label + changes. + (push_eh_cleanup): New routine to register a cleanup for an + exception object. + (empty_fndecl): Used to default cleanup actions to + nothing. + (init_exception_processing): Setup empty_fndecl. Setup + saved_cleanup. + (expand_start_catch_block): Update to reflect label changes. Call + push_eh_object to register the cleanup for the EH object. + (start_anon_func): New routine to start building lambda expressions + from trees. + (end_anon_func): New routine to end them. + (struct labelNode): Change so that we can use tree labels, or rtx + labels. + (saved_cleanup): Object to check for dynamic cleanups for the + exception handling object. + (push_label_entry): Change so that we can use tree labels, or rtx + labels. + (pop_label_entry): Likewise. + (top_label_entry): Likewise. + (expand_start_all_catch): Use tree label instead of rtx label, so + that we can get the magic of expand_goto. + (expand_end_all_catch): Update to reflect label changes. + + * class.c (build_vfn_ref): Remove building_cleanup logic, as we now + use UNSAVE_EXPRs. + * typeck.c (get_member_function_from_ptrfunc): Remove remnants of + building_cleanup logic, as we now use UNSAVE_EXPRs. + * cp-tree.h (unsave_expr): Declare it. + * decl.c (building_cleanup): Remove. + (maybe_build_cleanup): Remove building_cleanup logic, and use + UNSAVE_EXPR instead. + +Sun Dec 3 01:34:58 1995 Mike Stump + + * gc.c (build_t_desc): Update error message to say . + +Thu Nov 30 12:30:05 1995 Brendan Kehoe + + * decl.c (pushdecl): Only warn about shadowing a local variable if + warn_shadow is true. + +Sun Nov 26 16:06:55 1995 Rusty Russell + + * typeck.c (build_binary_op_nodefault): Added warning about + comparisons between different enum types with -Wall, unless + -fenum-int-equiv set. + +Wed Nov 22 15:44:02 1995 Mike Stump + + * class.c (finish_struct_1): Skip down to the inner type in + multidimensional arrays. Ensures ctors will be made for types that + need constructing. + +Wed Nov 22 14:19:22 1995 Mike Stump + + * decl.c (last_dtor_insn): New to track the last compiler generated + insn in a dtor. + (store_parm_decls): Set it. + (finish_function): Use it to see if the dtor is empty. Avoid doing + vtable setup all the time, if we can. + (struct cp_function): Add last_dtor_insn. + (push_cp_function_context): Save it. + (pop_cp_function_context): Restore it. + +Wed Nov 22 11:52:19 1995 Paul Russell + + * typeck.c (build_unary_op): Set TREE_NO_UNUSED_WARNING to avoid + warnings. + +Tue Nov 21 17:15:23 1995 Mike Stump + + * typeck.c (expand_target_expr): Make sure targets get put into the + current temp_slot_level, so that the free_temp_slots call will reuse + them. + +Tue Nov 21 13:32:03 1995 Mike Stump + + * class.c (finish_struct_1): Delay delta fixups for virtual bases + until after we have done the hard virtuals, to avoid a bogus `every + virtual function must have a unique final overrider' for virtual + functions that are only overridden by hard virtuals. + +Thu Nov 9 13:35:30 1995 Jason Merrill + + * pt.c (do_function_instantiation): Don't try to find a file-scope + template for a member function. + +Tue Nov 14 06:20:35 1995 Mike Stump + + * g++.c (main): Add handling of -nodefaultlibs. + +Mon Nov 13 15:45:34 1995 Mike Stump + + * cp-tree.h (INDIRECT_BIND): Add a way for the frontend to + distinguish between direct bindings of reference variables, and + indirect bindings of reference variables. + * cvt.c (build_up_reference): Use it. + * typeck.c (convert_arguments): Use it to indicate this is an + indirect binding. + * decl.c (cp_finish_decl): Ensure that we reuse stack slots as fast + as they are unused. + (expand_static_init): Likewise. + (cplus_expand_expr_stmt): Likewise. + * decl2.c (finish_file): Likewise. + * init.c (perform_member_init): Likewise. + (emit_base_init): Likewise. + (expand_aggr_vbase_init_1): Likewise. + +Fri Nov 10 09:18:09 1995 Brendan Kehoe + + * decl.c (push_namespace): Rewrite to use build_lang_decl, so we + get a DECL_LANG_SPECIFIC node. + * cp-tree.h (lang_decl_flags): Add new member `level'. + (NAMESPACE_LEVEL): Don't use decl.arguments, instead use the + decl_flags level member. + +Mon Nov 6 18:36:13 1995 Brendan Kehoe + + * call.c (build_method_call): Make sure instance has a + TYPE_LANG_SPECIFIC node before we dive into it. + +Sat Nov 4 20:01:52 1995 Jason Molenda + + * method.c (make_thunk): Use TREE_SET_CODE to set thunk's tree code. + +Thu Nov 2 17:56:57 1995 Mike Stump + + * decl.c (duplicate_decls): When smashing decls, smash staticness in + the usual way. + +Thu Nov 2 16:44:02 1995 Mike Stump + + * decl.c (poplevel): Handle the merging of subblocks of cleanups + when finishing blocks that have already been created (usually due to + the fixup goto code). Fixes bad debugging information. + +Wed Nov 1 12:33:53 1995 Jason Merrill + + * method.c (hack_identifier): Don't abort when we get a TREE_LIST + that's not a list of overloaded functions. + +Wed Nov 1 11:38:58 1995 Brendan Kehoe + + * decl2.c (mark_vtable_entries): Check DECL_LANG_SPECIFIC on fn + before trying to use DECL_ABSTRACT_VIRTUAL_P. + +Tue Oct 31 11:56:55 1995 Jason Merrill + + * decl2.c (mark_used): New function for hooking into setting of + TREE_USED on decls. + * call.c (build_method_call): Use it. + * class.c (instantiate_type): Likewise. + * init.c (build_offset_ref): Likewise. Don't call assemble_external + for all like-named functions. + * method.c (hack_identifier): Likewise. + (emit_thunk): Don't call assemble_external. + (make_thunk): Create thunk as a FUNCTION_DECL so that it + gets the right mode and ENCODE_SECTION_INFO works. + + * parse.y: Use mark_used. Pass operator names to do_identifier. + * lex.c (do_identifier): Handle operator names. + + * decl2.c (grokclassfn): Tweak __in_chrg attributes. + +Thu Oct 26 16:45:58 1995 Brendan Kehoe + + * errfn.c: Include stdio.h. + (cp_sprintf): Take out decl of sprintf, and cast sprintf to errorfn*. + +Wed Oct 25 18:58:41 1995 Mike Stump + + * typeck2.c (digest_init): Always convert initializers to the + right type. + +Wed Oct 25 13:25:24 1995 Mike Stump + + * init.c (member_init_ok_or_else): Don't allow member initializers + for indirect members, as it is invalid. + +Wed Oct 25 11:35:28 1995 Brendan Kehoe + + * decl.c (grokdeclarator): Don't allow `friend signed ()'. + +Fri Oct 20 10:30:59 1995 Mike Stump + + * parse.y (for.init.statement): Catch compound statements inside for + initializations, if we're being pedantic. + +Fri Oct 20 10:03:42 1995 Mike Stump + + * decl.c (lookup_tag): Return NULL_TREE if we don't find what we are + looking for. + +Thu Oct 19 14:26:10 1995 Mike Stump + + * error.c (dump_expr): Don't core dump when a boolean expression is + used as a default argument. + +Thu Oct 19 10:36:30 1995 Jason Merrill + + * class.c (finish_struct_bits): Check aggregate_value_p instead of + RETURN_IN_MEMORY. + +Wed Oct 18 18:12:32 1995 Jason Merrill + + * class.c (finish_struct_bits): Also set TREE_ADDRESSABLE on a + BLKmode type that would otherwise be returned in registers. + +Mon Oct 16 12:32:19 1995 Brendan Kehoe + + * g++.c (WITHLIBC): New macro. + (main): Declare saw_libc. Use WITHLIBC if `-lc' was used; set + saw_libc and pass it at the end if it was set. + +Wed Oct 11 16:30:34 1995 Brendan Kehoe + + * parse.y (fn.def1): Call split_specs_attrs in + declmods notype_declarator case. Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/ChangeLog ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/call.c =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/call.c (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/call.c (revision 60969) @@ -0,0 +1,4558 @@ +/* Functions related to invoking methods and overloaded functions. + Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@cygnus.com) and + modified by Brendan Kehoe (brendan@cygnus.com). + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +/* High-level class interface. */ + +#include "config.h" +#include "system.h" +#include "tree.h" +#include "cp-tree.h" +#include "output.h" +#include "flags.h" +#include "rtl.h" +#include "toplev.h" + +#include "obstack.h" +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +extern int inhibit_warnings; +extern tree ctor_label, dtor_label; + +static tree build_new_method_call PROTO((tree, tree, tree, tree, int)); + +static tree build_field_call PROTO((tree, tree, tree, tree)); +static tree find_scoped_type PROTO((tree, tree, tree)); +static struct z_candidate * tourney PROTO((struct z_candidate *)); +static int joust PROTO((struct z_candidate *, struct z_candidate *, int)); +static int compare_ics PROTO((tree, tree)); +static tree build_over_call PROTO((struct z_candidate *, tree, int)); +static tree convert_like PROTO((tree, tree)); +static void op_error PROTO((enum tree_code, enum tree_code, tree, tree, + tree, const char *)); +static tree build_object_call PROTO((tree, tree)); +static tree resolve_args PROTO((tree)); +static struct z_candidate * build_user_type_conversion_1 + PROTO ((tree, tree, int)); +static void print_z_candidates PROTO((struct z_candidate *)); +static tree build_this PROTO((tree)); +static struct z_candidate * splice_viable PROTO((struct z_candidate *)); +static int any_viable PROTO((struct z_candidate *)); +static struct z_candidate * add_template_candidate + PROTO((struct z_candidate *, tree, tree, tree, tree, int, + unification_kind_t)); +static struct z_candidate * add_template_candidate_real + PROTO((struct z_candidate *, tree, tree, tree, tree, int, + tree, unification_kind_t)); +static struct z_candidate * add_template_conv_candidate + PROTO((struct z_candidate *, tree, tree, tree, tree)); +static struct z_candidate * add_builtin_candidates + PROTO((struct z_candidate *, enum tree_code, enum tree_code, + tree, tree *, int)); +static struct z_candidate * add_builtin_candidate + PROTO((struct z_candidate *, enum tree_code, enum tree_code, + tree, tree, tree, tree *, tree *, int)); +static int is_complete PROTO((tree)); +static struct z_candidate * build_builtin_candidate + PROTO((struct z_candidate *, tree, tree, tree, tree *, tree *, + int)); +static struct z_candidate * add_conv_candidate + PROTO((struct z_candidate *, tree, tree, tree)); +static struct z_candidate * add_function_candidate + PROTO((struct z_candidate *, tree, tree, int)); +static tree implicit_conversion PROTO((tree, tree, tree, int)); +static tree standard_conversion PROTO((tree, tree, tree)); +static tree reference_binding PROTO((tree, tree, tree, int)); +static tree strip_top_quals PROTO((tree)); +static tree non_reference PROTO((tree)); +static tree build_conv PROTO((enum tree_code, tree, tree)); +static int is_subseq PROTO((tree, tree)); +static int maybe_handle_ref_bind PROTO((tree*, tree*)); +static void maybe_handle_implicit_object PROTO((tree*)); +static struct z_candidate * add_candidate PROTO((struct z_candidate *, + tree, tree, int)); +static tree source_type PROTO((tree)); +static void add_warning PROTO((struct z_candidate *, struct z_candidate *)); + +tree +build_vfield_ref (datum, type) + tree datum, type; +{ + tree rval; + + if (datum == error_mark_node) + return error_mark_node; + + if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE) + datum = convert_from_reference (datum); + + if (! TYPE_USES_COMPLEX_INHERITANCE (type)) + rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)), + datum, CLASSTYPE_VFIELD (type)); + else + rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), NULL_TREE, 0); + + return rval; +} + +/* Build a call to a member of an object. I.e., one that overloads + operator ()(), or is a pointer-to-function or pointer-to-method. */ + +static tree +build_field_call (basetype_path, instance_ptr, name, parms) + tree basetype_path, instance_ptr, name, parms; +{ + tree field, instance; + + if (name == ctor_identifier || name == dtor_identifier) + return NULL_TREE; + + /* Speed up the common case. */ + if (instance_ptr == current_class_ptr + && IDENTIFIER_CLASS_VALUE (name) == NULL_TREE) + return NULL_TREE; + + field = lookup_field (basetype_path, name, 1, 0); + + if (field == error_mark_node || field == NULL_TREE) + return field; + + if (TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL) + { + /* If it's a field, try overloading operator (), + or calling if the field is a pointer-to-function. */ + instance = build_indirect_ref (instance_ptr, NULL_PTR); + instance = build_component_ref_1 (instance, field, 0); + + if (instance == error_mark_node) + return error_mark_node; + + if (IS_AGGR_TYPE (TREE_TYPE (instance))) + return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, + instance, parms, NULL_TREE); + else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE) + { + if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE) + return build_function_call (instance, parms); + else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) + == METHOD_TYPE) + return build_function_call + (instance, expr_tree_cons (NULL_TREE, instance_ptr, parms)); + } + } + + return NULL_TREE; +} + +static tree +find_scoped_type (type, inner_name, inner_types) + tree type, inner_name, inner_types; +{ + tree tags = CLASSTYPE_TAGS (type); + + while (tags) + { + /* The TREE_PURPOSE of an enum tag (which becomes a member of the + enclosing class) is set to the name for the enum type. So, if + inner_name is `bar', and we strike `baz' for `enum bar { baz }', + then this test will be true. */ + if (TREE_PURPOSE (tags) == inner_name) + { + if (inner_types == NULL_TREE) + return TYPE_MAIN_DECL (TREE_VALUE (tags)); + return resolve_scope_to_name (TREE_VALUE (tags), inner_types); + } + tags = TREE_CHAIN (tags); + } + + /* Look for a TYPE_DECL. */ + for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags)) + if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name) + { + /* Code by raeburn. */ + if (inner_types == NULL_TREE) + return tags; + return resolve_scope_to_name (TREE_TYPE (tags), inner_types); + } + + return NULL_TREE; +} + +/* Resolve an expression NAME1::NAME2::...::NAMEn to + the name that names the above nested type. INNER_TYPES + is a chain of nested type names (held together by SCOPE_REFs); + OUTER_TYPE is the type we know to enclose INNER_TYPES. + Returns NULL_TREE if there is an error. */ + +tree +resolve_scope_to_name (outer_type, inner_stuff) + tree outer_type, inner_stuff; +{ + register tree tmp; + tree inner_name, inner_type; + + if (outer_type == NULL_TREE && current_class_type != NULL_TREE) + { + /* We first try to look for a nesting in our current class context, + then try any enclosing classes. */ + tree type = current_class_type; + + while (type && (TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE)) + { + tree rval = resolve_scope_to_name (type, inner_stuff); + + if (rval != NULL_TREE) + return rval; + type = DECL_CONTEXT (TYPE_MAIN_DECL (type)); + } + } + + if (TREE_CODE (inner_stuff) == SCOPE_REF) + { + inner_name = TREE_OPERAND (inner_stuff, 0); + inner_type = TREE_OPERAND (inner_stuff, 1); + } + else + { + inner_name = inner_stuff; + inner_type = NULL_TREE; + } + + if (outer_type == NULL_TREE) + { + tree x; + /* If we have something that's already a type by itself, + use that. */ + if (IDENTIFIER_HAS_TYPE_VALUE (inner_name)) + { + if (inner_type) + return resolve_scope_to_name (IDENTIFIER_TYPE_VALUE (inner_name), + inner_type); + return inner_name; + } + + x = lookup_name (inner_name, 0); + + if (x && TREE_CODE (x) == NAMESPACE_DECL) + { + x = lookup_namespace_name (x, inner_type); + return x; + } + return NULL_TREE; + } + + if (! IS_AGGR_TYPE (outer_type)) + return NULL_TREE; + + /* Look for member classes or enums. */ + tmp = find_scoped_type (outer_type, inner_name, inner_type); + + /* If it's not a type in this class, then go down into the + base classes and search there. */ + if (! tmp && TYPE_BINFO (outer_type)) + { + tree binfos = TYPE_BINFO_BASETYPES (outer_type); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tmp = resolve_scope_to_name (BINFO_TYPE (base_binfo), inner_stuff); + if (tmp) + return tmp; + } + tmp = NULL_TREE; + } + + return tmp; +} + +/* Returns nonzero iff the destructor name specified in NAME + (a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many + forms... */ + +int +check_dtor_name (basetype, name) + tree basetype, name; +{ + name = TREE_OPERAND (name, 0); + + /* Just accept something we've already complained about. */ + if (name == error_mark_node) + return 1; + + if (TREE_CODE (name) == TYPE_DECL) + name = TREE_TYPE (name); + else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') + /* OK */; + else if (TREE_CODE (name) == IDENTIFIER_NODE) + { + if ((IS_AGGR_TYPE (basetype) && name == constructor_name (basetype)) + || (TREE_CODE (basetype) == ENUMERAL_TYPE + && name == TYPE_IDENTIFIER (basetype))) + name = basetype; + else + name = get_type_value (name); + } + else + my_friendly_abort (980605); + + if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name)) + return 1; + return 0; +} + +/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'. + This is how virtual function calls are avoided. */ + +tree +build_scoped_method_call (exp, basetype, name, parms) + tree exp, basetype, name, parms; +{ + /* Because this syntactic form does not allow + a pointer to a base class to be `stolen', + we need not protect the derived->base conversion + that happens here. + + @@ But we do have to check access privileges later. */ + tree binfo, decl; + tree type = TREE_TYPE (exp); + + if (type == error_mark_node + || basetype == error_mark_node) + return error_mark_node; + + if (processing_template_decl) + { + if (TREE_CODE (name) == BIT_NOT_EXPR + && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE) + { + tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0); + if (type) + name = build_min_nt (BIT_NOT_EXPR, type); + } + name = build_min_nt (SCOPE_REF, basetype, name); + return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE); + } + + if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); + + if (TREE_CODE (basetype) == TREE_VEC) + { + binfo = basetype; + basetype = BINFO_TYPE (binfo); + } + else + binfo = NULL_TREE; + + /* Check the destructor call syntax. */ + if (TREE_CODE (name) == BIT_NOT_EXPR) + { + /* We can get here if someone writes their destructor call like + `obj.NS::~T()'; this isn't really a scoped method call, so hand + it off. */ + if (TREE_CODE (basetype) == NAMESPACE_DECL) + return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL); + + if (! check_dtor_name (basetype, name)) + cp_error ("qualified type `%T' does not match destructor name `~%T'", + basetype, TREE_OPERAND (name, 0)); + + /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note + that explicit ~int is caught in the parser; this deals with typedefs + and template parms. */ + if (! IS_AGGR_TYPE (basetype)) + { + if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype)) + cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')", + exp, basetype, type); + + return cp_convert (void_type_node, exp); + } + } + + if (! is_aggr_type (basetype, 1)) + return error_mark_node; + + if (! IS_AGGR_TYPE (type)) + { + cp_error ("base object `%E' of scoped method call is of non-aggregate type `%T'", + exp, type); + return error_mark_node; + } + + if (! binfo) + { + binfo = get_binfo (basetype, type, 1); + if (binfo == error_mark_node) + return error_mark_node; + if (! binfo) + error_not_base_type (basetype, type); + } + + if (binfo) + { + if (TREE_CODE (exp) == INDIRECT_REF) + decl = build_indirect_ref + (convert_pointer_to_real + (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR); + else + decl = build_scoped_ref (exp, basetype); + + /* Call to a destructor. */ + if (TREE_CODE (name) == BIT_NOT_EXPR) + { + if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl))) + return cp_convert (void_type_node, exp); + + return build_delete (TREE_TYPE (decl), decl, integer_two_node, + LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, + 0); + } + + /* Call to a method. */ + return build_method_call (decl, name, parms, binfo, + LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); + } + return error_mark_node; +} + +/* We want the address of a function or method. We avoid creating a + pointer-to-member function. */ + +tree +build_addr_func (function) + tree function; +{ + tree type = TREE_TYPE (function); + + /* We have to do these by hand to avoid real pointer to member + functions. */ + if (TREE_CODE (type) == METHOD_TYPE) + { + tree addr; + + type = build_pointer_type (type); + + if (mark_addressable (function) == 0) + return error_mark_node; + + addr = build1 (ADDR_EXPR, type, function); + + /* Address of a static or external variable or function counts + as a constant */ + if (staticp (function)) + TREE_CONSTANT (addr) = 1; + + function = addr; + } + else + function = default_conversion (function); + + return function; +} + +/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or + POINTER_TYPE to those. Note, pointer to member function types + (TYPE_PTRMEMFUNC_P) must be handled by our callers. */ + +tree +build_call (function, result_type, parms) + tree function, result_type, parms; +{ + int is_constructor = 0; + tree tmp; + tree decl; + + function = build_addr_func (function); + + if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function))) + { + sorry ("unable to call pointer to member function here"); + return error_mark_node; + } + + if (TREE_CODE (function) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) + decl = TREE_OPERAND (function, 0); + else + decl = NULL_TREE; + + if (decl && DECL_CONSTRUCTOR_P (decl)) + is_constructor = 1; + + if (decl) + my_friendly_assert (TREE_USED (decl), 990125); + + /* Don't pass empty class objects by value. This is useful + for tags in STL, which are used to control overload resolution. + We don't need to handle other cases of copying empty classes. */ + if (! decl || ! DECL_BUILT_IN (decl)) + for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp)) + if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp))) + && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp)))) + { + tree t = make_node (RTL_EXPR); + TREE_TYPE (t) = TREE_TYPE (TREE_VALUE (tmp)); + RTL_EXPR_RTL (t) = const0_rtx; + RTL_EXPR_SEQUENCE (t) = NULL_RTX; + TREE_VALUE (tmp) = build (COMPOUND_EXPR, TREE_TYPE (t), + TREE_VALUE (tmp), t); + } + + function = build_nt (CALL_EXPR, function, parms, NULL_TREE); + TREE_HAS_CONSTRUCTOR (function) = is_constructor; + TREE_TYPE (function) = result_type; + TREE_SIDE_EFFECTS (function) = 1; + + return function; +} + +/* Build something of the form ptr->method (args) + or object.method (args). This can also build + calls to constructors, and find friends. + + Member functions always take their class variable + as a pointer. + + INSTANCE is a class instance. + + NAME is the name of the method desired, usually an IDENTIFIER_NODE. + + PARMS help to figure out what that NAME really refers to. + + BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE + down to the real instance type to use for access checking. We need this + information to get protected accesses correct. This parameter is used + by build_member_call. + + FLAGS is the logical disjunction of zero or more LOOKUP_ + flags. See cp-tree.h for more info. + + If this is all OK, calls build_function_call with the resolved + member function. + + This function must also handle being called to perform + initialization, promotion/coercion of arguments, and + instantiation of default parameters. + + Note that NAME may refer to an instance variable name. If + `operator()()' is defined for the type of that field, then we return + that result. */ + +tree +build_method_call (instance, name, parms, basetype_path, flags) + tree instance, name, parms, basetype_path; + int flags; +{ + tree basetype, instance_ptr; + +#ifdef GATHER_STATISTICS + n_build_method_call++; +#endif + + if (instance == error_mark_node + || name == error_mark_node + || parms == error_mark_node + || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node)) + return error_mark_node; + + if (processing_template_decl) + { + /* We need to process template parm names here so that tsubst catches + them properly. Other type names can wait. */ + if (TREE_CODE (name) == BIT_NOT_EXPR) + { + tree type = NULL_TREE; + + if (TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE) + type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0); + else if (TREE_CODE (TREE_OPERAND (name, 0)) == TYPE_DECL) + type = TREE_TYPE (TREE_OPERAND (name, 0)); + + if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM) + name = build_min_nt (BIT_NOT_EXPR, type); + } + + return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE); + } + + if (TREE_CODE (name) == BIT_NOT_EXPR) + { + if (parms) + error ("destructors take no parameters"); + basetype = TREE_TYPE (instance); + if (TREE_CODE (basetype) == REFERENCE_TYPE) + basetype = TREE_TYPE (basetype); + + if (! check_dtor_name (basetype, name)) + cp_error + ("destructor name `~%T' does not match type `%T' of expression", + TREE_OPERAND (name, 0), basetype); + + if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype))) + return cp_convert (void_type_node, instance); + instance = default_conversion (instance); + instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); + return build_delete (build_pointer_type (basetype), + instance_ptr, integer_two_node, + LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); + } + + return build_new_method_call (instance, name, parms, basetype_path, flags); +} + +/* New overloading code. */ + +struct z_candidate { + tree fn; + tree convs; + tree second_conv; + int viable; + tree basetype_path; + tree template; + tree warnings; + struct z_candidate *next; +}; + +#define IDENTITY_RANK 0 +#define EXACT_RANK 1 +#define PROMO_RANK 2 +#define STD_RANK 3 +#define PBOOL_RANK 4 +#define USER_RANK 5 +#define ELLIPSIS_RANK 6 +#define BAD_RANK 7 + +#define ICS_RANK(NODE) \ + (ICS_BAD_FLAG (NODE) ? BAD_RANK \ + : ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK \ + : ICS_USER_FLAG (NODE) ? USER_RANK \ + : ICS_STD_RANK (NODE)) + +#define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE) + +#define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE) +#define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) +#define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE) +#define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE) + +#define USER_CONV_CAND(NODE) \ + ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1))) +#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn) + +int +null_ptr_cst_p (t) + tree t; +{ + if (t == null_node + || (integer_zerop (t) && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)) + return 1; + return 0; +} + +static tree +build_conv (code, type, from) + enum tree_code code; + tree type, from; +{ + tree t = build1 (code, type, from); + int rank = ICS_STD_RANK (from); + switch (code) + { + case PTR_CONV: + case PMEM_CONV: + case BASE_CONV: + case STD_CONV: + if (rank < STD_RANK) + rank = STD_RANK; + break; + + case QUAL_CONV: + if (rank < EXACT_RANK) + rank = EXACT_RANK; + + default: + break; + } + ICS_STD_RANK (t) = rank; + ICS_USER_FLAG (t) = ICS_USER_FLAG (from); + ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from); + return t; +} + +static tree +non_reference (t) + tree t; +{ + if (TREE_CODE (t) == REFERENCE_TYPE) + t = TREE_TYPE (t); + return t; +} + +static tree +strip_top_quals (t) + tree t; +{ + if (TREE_CODE (t) == ARRAY_TYPE) + return t; + return TYPE_MAIN_VARIANT (t); +} + +/* Returns the standard conversion path (see [conv]) from type FROM to type + TO, if any. For proper handling of null pointer constants, you must + also pass the expression EXPR to convert from. */ + +static tree +standard_conversion (to, from, expr) + tree to, from, expr; +{ + enum tree_code fcode, tcode; + tree conv; + int fromref = 0; + + if (TREE_CODE (to) == REFERENCE_TYPE) + to = TREE_TYPE (to); + if (TREE_CODE (from) == REFERENCE_TYPE) + { + fromref = 1; + from = TREE_TYPE (from); + } + to = strip_top_quals (to); + from = strip_top_quals (from); + + if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to)) + && expr && type_unknown_p (expr)) + { + expr = instantiate_type (to, expr, 0); + if (expr == error_mark_node) + return NULL_TREE; + from = TREE_TYPE (expr); + } + + fcode = TREE_CODE (from); + tcode = TREE_CODE (to); + + conv = build1 (IDENTITY_CONV, from, expr); + + if (fcode == FUNCTION_TYPE) + { + from = build_pointer_type (from); + fcode = TREE_CODE (from); + conv = build_conv (LVALUE_CONV, from, conv); + } + else if (fcode == ARRAY_TYPE) + { + from = build_pointer_type (TREE_TYPE (from)); + fcode = TREE_CODE (from); + conv = build_conv (LVALUE_CONV, from, conv); + } + else if (fromref || (expr && real_lvalue_p (expr))) + conv = build_conv (RVALUE_CONV, from, conv); + + if (from == to) + return conv; + + if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to)) + && expr && null_ptr_cst_p (expr)) + { + conv = build_conv (STD_CONV, to, conv); + } + else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE) + { + enum tree_code ufcode = TREE_CODE (TREE_TYPE (from)); + enum tree_code utcode = TREE_CODE (TREE_TYPE (to)); + + if (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (from)), + TYPE_MAIN_VARIANT (TREE_TYPE (to)))) + ; + else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE + && ufcode != FUNCTION_TYPE) + { + from = build_pointer_type + (cp_build_qualified_type (void_type_node, + CP_TYPE_QUALS (TREE_TYPE (from)))); + conv = build_conv (PTR_CONV, from, conv); + } + else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE) + { + tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from)); + tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to)); + + if (DERIVED_FROM_P (fbase, tbase) + && (same_type_p + (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))), + TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to)))))) + { + from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from))); + from = build_pointer_type (from); + conv = build_conv (PMEM_CONV, from, conv); + } + } + else if (IS_AGGR_TYPE (TREE_TYPE (from)) + && IS_AGGR_TYPE (TREE_TYPE (to))) + { + if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from))) + { + from = + cp_build_qualified_type (TREE_TYPE (to), + CP_TYPE_QUALS (TREE_TYPE (from))); + from = build_pointer_type (from); + conv = build_conv (PTR_CONV, from, conv); + } + } + + if (same_type_p (from, to)) + /* OK */; + else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from))) + conv = build_conv (QUAL_CONV, to, conv); + else if (expr && string_conv_p (to, expr, 0)) + /* converting from string constant to char *. */ + conv = build_conv (QUAL_CONV, to, conv); + else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from))) + { + conv = build_conv (PTR_CONV, to, conv); + ICS_BAD_FLAG (conv) = 1; + } + else + return 0; + + from = to; + } + else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from)) + { + tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from)); + tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to)); + tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn))); + tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn))); + + if (! DERIVED_FROM_P (fbase, tbase) + || ! same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn)) + || ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)), + TREE_CHAIN (TYPE_ARG_TYPES (tofn))) + || CP_TYPE_QUALS (fbase) != CP_TYPE_QUALS (tbase)) + return 0; + + from = cp_build_qualified_type (tbase, CP_TYPE_QUALS (fbase)); + from = build_cplus_method_type (from, TREE_TYPE (fromfn), + TREE_CHAIN (TYPE_ARG_TYPES (fromfn))); + from = build_ptrmemfunc_type (build_pointer_type (from)); + conv = build_conv (PMEM_CONV, from, conv); + } + else if (tcode == BOOLEAN_TYPE) + { + if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE + || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))) + return 0; + + conv = build_conv (STD_CONV, to, conv); + if (fcode == POINTER_TYPE + || (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK)) + ICS_STD_RANK (conv) = PBOOL_RANK; + } + /* We don't check for ENUMERAL_TYPE here because there are no standard + conversions to enum type. */ + else if (tcode == INTEGER_TYPE || tcode == BOOLEAN_TYPE + || tcode == REAL_TYPE) + { + if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)) + return 0; + conv = build_conv (STD_CONV, to, conv); + + /* Give this a better rank if it's a promotion. */ + if (to == type_promotes_to (from) + && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK) + ICS_STD_RANK (conv) = PROMO_RANK; + } + else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) + && DERIVED_FROM_P (to, from)) + { + if (TREE_CODE (conv) == RVALUE_CONV) + conv = TREE_OPERAND (conv, 0); + conv = build_conv (BASE_CONV, to, conv); + } + else + return 0; + + return conv; +} + +/* Returns the conversion path from type FROM to reference type TO for + purposes of reference binding. For lvalue binding, either pass a + reference type to FROM or an lvalue expression to EXPR. + + Currently does not distinguish in the generated trees between binding to + an lvalue and a temporary. Should it? */ + +static tree +reference_binding (rto, rfrom, expr, flags) + tree rto, rfrom, expr; + int flags; +{ + tree conv; + int lvalue = 1; + tree to = TREE_TYPE (rto); + tree from = rfrom; + int related; + + if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr)) + { + expr = instantiate_type (to, expr, 0); + if (expr == error_mark_node) + return NULL_TREE; + from = TREE_TYPE (expr); + } + + if (TREE_CODE (from) == REFERENCE_TYPE) + from = TREE_TYPE (from); + else if (! expr || ! real_lvalue_p (expr)) + lvalue = 0; + + related = (same_type_p (TYPE_MAIN_VARIANT (to), + TYPE_MAIN_VARIANT (from)) + || (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) + && DERIVED_FROM_P (to, from))); + + if (lvalue && related && at_least_as_qualified_p (to, from)) + { + conv = build1 (IDENTITY_CONV, from, expr); + + if (same_type_p (TYPE_MAIN_VARIANT (to), + TYPE_MAIN_VARIANT (from))) + conv = build_conv (REF_BIND, rto, conv); + else + { + conv = build_conv (REF_BIND, rto, conv); + ICS_STD_RANK (conv) = STD_RANK; + } + } + else + conv = NULL_TREE; + + if (! conv) + { + conv = standard_conversion (to, rfrom, expr); + if (conv) + { + conv = build_conv (REF_BIND, rto, conv); + + /* Bind directly to a base subobject of a class rvalue. Do it + after building the conversion for proper handling of ICS_RANK. */ + if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV) + TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0); + } + if (conv + && ((! (CP_TYPE_CONST_NON_VOLATILE_P (to) + && (flags & LOOKUP_NO_TEMP_BIND) == 0)) + /* If T1 is reference-related to T2, cv1 must be the same + cv-qualification as, or greater cv-qualification than, + cv2; otherwise, the program is ill-formed. */ + || (related && !at_least_as_qualified_p (to, from)))) + ICS_BAD_FLAG (conv) = 1; + } + + return conv; +} + +/* Returns the implicit conversion sequence (see [over.ics]) from type FROM + to type TO. The optional expression EXPR may affect the conversion. + FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is + significant. */ + +static tree +implicit_conversion (to, from, expr, flags) + tree to, from, expr; + int flags; +{ + tree conv; + struct z_candidate *cand; + + if (TREE_CODE (to) == REFERENCE_TYPE) + conv = reference_binding (to, from, expr, flags); + else + conv = standard_conversion (to, from, expr); + + if (conv) + ; + else if (expr != NULL_TREE + && (IS_AGGR_TYPE (non_reference (from)) + || IS_AGGR_TYPE (non_reference (to))) + && (flags & LOOKUP_NO_CONVERSION) == 0) + { + cand = build_user_type_conversion_1 + (to, expr, LOOKUP_ONLYCONVERTING); + if (cand) + conv = cand->second_conv; + if ((! conv || ICS_BAD_FLAG (conv)) + && TREE_CODE (to) == REFERENCE_TYPE + && (flags & LOOKUP_NO_TEMP_BIND) == 0) + { + cand = build_user_type_conversion_1 + (TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING); + if (cand) + { + if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (to))) + ICS_BAD_FLAG (cand->second_conv) = 1; + if (!conv || (ICS_BAD_FLAG (conv) + > ICS_BAD_FLAG (cand->second_conv))) + conv = build_conv (REF_BIND, to, cand->second_conv); + } + } + } + + return conv; +} + +/* Add a new entry to the list of candidates. Used by the add_*_candidate + functions. */ + +static struct z_candidate * +add_candidate (candidates, fn, convs, viable) + struct z_candidate *candidates; + tree fn, convs; + int viable; +{ + struct z_candidate *cand + = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate)); + + cand->fn = fn; + cand->convs = convs; + cand->second_conv = NULL_TREE; + cand->viable = viable; + cand->basetype_path = NULL_TREE; + cand->template = NULL_TREE; + cand->warnings = NULL_TREE; + cand->next = candidates; + + return cand; +} + +/* Create an overload candidate for the function or method FN called with + the argument list ARGLIST and add it to CANDIDATES. FLAGS is passed on + to implicit_conversion. */ + +static struct z_candidate * +add_function_candidate (candidates, fn, arglist, flags) + struct z_candidate *candidates; + tree fn, arglist; + int flags; +{ + tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); + int i, len; + tree convs; + tree parmnode, argnode; + int viable = 1; + + /* The `this', `in_chrg', and `vlist' arguments to constructors are + not considered in overload resolution. */ + if (DECL_CONSTRUCTOR_P (fn)) + { + parmlist = TREE_CHAIN (parmlist); + arglist = TREE_CHAIN (arglist); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) + { + parmlist = TREE_CHAIN (parmlist); + arglist = TREE_CHAIN (arglist); + } + if ((flags & LOOKUP_HAS_VLIST) + && DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) + { + parmlist = TREE_CHAIN (parmlist); + arglist = TREE_CHAIN (arglist); + } + else if (!(flags & LOOKUP_HAS_VLIST) + && !DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) + /* Ok */; + else + { + /* The ctor expects a vlist and the arguments don't have + one, or vice versa, so fn is not even a candidate, since + the corresponding ctor would be the candidate. */ + return candidates; + } + } + + len = list_length (arglist); + convs = make_scratch_vec (len); + + /* 13.3.2 - Viable functions [over.match.viable] + First, to be a viable function, a candidate function shall have enough + parameters to agree in number with the arguments in the list. + + We need to check this first; otherwise, checking the ICSes might cause + us to produce an ill-formed template instantiation. */ + + parmnode = parmlist; + for (i = 0; i < len; ++i) + { + if (parmnode == NULL_TREE || parmnode == void_list_node) + break; + parmnode = TREE_CHAIN (parmnode); + } + + if (i < len && parmnode) + viable = 0; + + /* Make sure there are default args for the rest of the parms. */ + else for (; parmnode && parmnode != void_list_node; + parmnode = TREE_CHAIN (parmnode)) + if (! TREE_PURPOSE (parmnode)) + { + viable = 0; + break; + } + + if (! viable) + goto out; + + /* Second, for F to be a viable function, there shall exist for each + argument an implicit conversion sequence that converts that argument + to the corresponding parameter of F. */ + + parmnode = parmlist; + argnode = arglist; + + for (i = 0; i < len; ++i) + { + tree arg = TREE_VALUE (argnode); + tree argtype = lvalue_type (arg); + tree t; + + if (parmnode == void_list_node) + break; + + if (parmnode) + { + tree parmtype = TREE_VALUE (parmnode); + + /* [over.match.funcs] For conversion functions, the function is + considered to be a member of the class of the implicit object + argument for the purpose of defining the type of the implicit + object parameter. + + Since build_over_call ignores the ICS for the `this' parameter, + we can just change the parm type. */ + if (DECL_CONV_FN_P (fn) && i == 0) + { + parmtype + = build_qualified_type (TREE_TYPE (argtype), + TYPE_QUALS (TREE_TYPE (parmtype))); + parmtype = build_pointer_type (parmtype); + } + + t = implicit_conversion (parmtype, argtype, arg, flags); + } + else + { + t = build1 (IDENTITY_CONV, argtype, arg); + ICS_ELLIPSIS_FLAG (t) = 1; + } + + if (i == 0 && t && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE + && ! DECL_CONSTRUCTOR_P (fn)) + ICS_THIS_FLAG (t) = 1; + + TREE_VEC_ELT (convs, i) = t; + if (! t) + { + viable = 0; + break; + } + + if (ICS_BAD_FLAG (t)) + viable = -1; + + if (parmnode) + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); + } + + out: + return add_candidate (candidates, fn, convs, viable); +} + +/* Create an overload candidate for the conversion function FN which will + be invoked for expression OBJ, producing a pointer-to-function which + will in turn be called with the argument list ARGLIST, and add it to + CANDIDATES. FLAGS is passed on to implicit_conversion. + + Actually, we don't really care about FN; we care about the type it + converts to. There may be multiple conversion functions that will + convert to that type, and we rely on build_user_type_conversion_1 to + choose the best one; so when we create our candidate, we record the type + instead of the function. */ + +static struct z_candidate * +add_conv_candidate (candidates, fn, obj, arglist) + struct z_candidate *candidates; + tree fn, obj, arglist; +{ + tree totype = TREE_TYPE (TREE_TYPE (fn)); + tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype)); + int i, len = list_length (arglist) + 1; + tree convs = make_scratch_vec (len); + tree parmnode = parmlist; + tree argnode = arglist; + int viable = 1; + int flags = LOOKUP_NORMAL; + + /* Don't bother looking up the same type twice. */ + if (candidates && candidates->fn == totype) + return candidates; + + for (i = 0; i < len; ++i) + { + tree arg = i == 0 ? obj : TREE_VALUE (argnode); + tree argtype = lvalue_type (arg); + tree t; + + if (i == 0) + t = implicit_conversion (totype, argtype, arg, flags); + else if (parmnode == void_list_node) + break; + else if (parmnode) + t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); + else + { + t = build1 (IDENTITY_CONV, argtype, arg); + ICS_ELLIPSIS_FLAG (t) = 1; + } + + TREE_VEC_ELT (convs, i) = t; + if (! t) + break; + + if (ICS_BAD_FLAG (t)) + viable = -1; + + if (i == 0) + continue; + + if (parmnode) + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); + } + + if (i < len) + viable = 0; + + for (; parmnode && parmnode != void_list_node; + parmnode = TREE_CHAIN (parmnode)) + if (! TREE_PURPOSE (parmnode)) + { + viable = 0; + break; + } + + return add_candidate (candidates, totype, convs, viable); +} + +static struct z_candidate * +build_builtin_candidate (candidates, fnname, type1, type2, + args, argtypes, flags) + struct z_candidate *candidates; + tree fnname, type1, type2, *args, *argtypes; + int flags; + +{ + tree t, convs; + int viable = 1, i; + tree types[2]; + + types[0] = type1; + types[1] = type2; + + convs = make_scratch_vec (args[2] ? 3 : (args[1] ? 2 : 1)); + + for (i = 0; i < 2; ++i) + { + if (! args[i]) + break; + + t = implicit_conversion (types[i], argtypes[i], args[i], flags); + if (! t) + { + viable = 0; + /* We need something for printing the candidate. */ + t = build1 (IDENTITY_CONV, types[i], NULL_TREE); + } + else if (ICS_BAD_FLAG (t)) + viable = 0; + TREE_VEC_ELT (convs, i) = t; + } + + /* For COND_EXPR we rearranged the arguments; undo that now. */ + if (args[2]) + { + TREE_VEC_ELT (convs, 2) = TREE_VEC_ELT (convs, 1); + TREE_VEC_ELT (convs, 1) = TREE_VEC_ELT (convs, 0); + t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags); + if (t) + TREE_VEC_ELT (convs, 0) = t; + else + viable = 0; + } + + return add_candidate (candidates, fnname, convs, viable); +} + +static int +is_complete (t) + tree t; +{ + return TYPE_SIZE (complete_type (t)) != NULL_TREE; +} + +/* Create any builtin operator overload candidates for the operator in + question given the converted operand types TYPE1 and TYPE2. The other + args are passed through from add_builtin_candidates to + build_builtin_candidate. */ + +static struct z_candidate * +add_builtin_candidate (candidates, code, code2, fnname, type1, type2, + args, argtypes, flags) + struct z_candidate *candidates; + enum tree_code code, code2; + tree fnname, type1, type2, *args, *argtypes; + int flags; +{ + switch (code) + { + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + args[1] = integer_zero_node; + type2 = integer_type_node; + break; + default: + break; + } + + switch (code) + { + +/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type, + and VQ is either volatile or empty, there exist candidate operator + functions of the form + VQ T& operator++(VQ T&); + T operator++(VQ T&, int); + 5 For every pair T, VQ), where T is an enumeration type or an arithmetic + type other than bool, and VQ is either volatile or empty, there exist + candidate operator functions of the form + VQ T& operator--(VQ T&); + T operator--(VQ T&, int); + 6 For every pair T, VQ), where T is a cv-qualified or cv-unqualified + complete object type, and VQ is either volatile or empty, there exist + candidate operator functions of the form + T*VQ& operator++(T*VQ&); + T*VQ& operator--(T*VQ&); + T* operator++(T*VQ&, int); + T* operator--(T*VQ&, int); */ + + case POSTDECREMENT_EXPR: + case PREDECREMENT_EXPR: + if (TREE_CODE (type1) == BOOLEAN_TYPE) + return candidates; + case POSTINCREMENT_EXPR: + case PREINCREMENT_EXPR: + if ((ARITHMETIC_TYPE_P (type1) && TREE_CODE (type1) != ENUMERAL_TYPE) + || TYPE_PTROB_P (type1)) + { + type1 = build_reference_type (type1); + break; + } + return candidates; + +/* 7 For every cv-qualified or cv-unqualified complete object type T, there + exist candidate operator functions of the form + + T& operator*(T*); + + 8 For every function type T, there exist candidate operator functions of + the form + T& operator*(T*); */ + + case INDIRECT_REF: + if (TREE_CODE (type1) == POINTER_TYPE + && (TYPE_PTROB_P (type1) + || TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)) + break; + return candidates; + +/* 9 For every type T, there exist candidate operator functions of the form + T* operator+(T*); + + 10For every promoted arithmetic type T, there exist candidate operator + functions of the form + T operator+(T); + T operator-(T); */ + + case CONVERT_EXPR: /* unary + */ + if (TREE_CODE (type1) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE) + break; + case NEGATE_EXPR: + if (ARITHMETIC_TYPE_P (type1)) + break; + return candidates; + +/* 11For every promoted integral type T, there exist candidate operator + functions of the form + T operator~(T); */ + + case BIT_NOT_EXPR: + if (INTEGRAL_TYPE_P (type1)) + break; + return candidates; + +/* 12For every quintuple C1, C2, T, CV1, CV2), where C2 is a class type, C1 + is the same type as C2 or is a derived class of C2, T is a complete + object type or a function type, and CV1 and CV2 are cv-qualifier-seqs, + there exist candidate operator functions of the form + CV12 T& operator->*(CV1 C1*, CV2 T C2::*); + where CV12 is the union of CV1 and CV2. */ + + case MEMBER_REF: + if (TREE_CODE (type1) == POINTER_TYPE + && (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))) + { + tree c1 = TREE_TYPE (type1); + tree c2 = (TYPE_PTRMEMFUNC_P (type2) + ? TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2))) + : TYPE_OFFSET_BASETYPE (TREE_TYPE (type2))); + + if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1) + && (TYPE_PTRMEMFUNC_P (type2) + || is_complete (TREE_TYPE (TREE_TYPE (type2))))) + break; + } + return candidates; + +/* 13For every pair of promoted arithmetic types L and R, there exist can- + didate operator functions of the form + LR operator*(L, R); + LR operator/(L, R); + LR operator+(L, R); + LR operator-(L, R); + bool operator<(L, R); + bool operator>(L, R); + bool operator<=(L, R); + bool operator>=(L, R); + bool operator==(L, R); + bool operator!=(L, R); + where LR is the result of the usual arithmetic conversions between + types L and R. + + 14For every pair of types T and I, where T is a cv-qualified or cv- + unqualified complete object type and I is a promoted integral type, + there exist candidate operator functions of the form + T* operator+(T*, I); + T& operator[](T*, I); + T* operator-(T*, I); + T* operator+(I, T*); + T& operator[](I, T*); + + 15For every T, where T is a pointer to complete object type, there exist + candidate operator functions of the form112) + ptrdiff_t operator-(T, T); + + 16For every pointer type T, there exist candidate operator functions of + the form + bool operator<(T, T); + bool operator>(T, T); + bool operator<=(T, T); + bool operator>=(T, T); + bool operator==(T, T); + bool operator!=(T, T); + + 17For every pointer to member type T, there exist candidate operator + functions of the form + bool operator==(T, T); + bool operator!=(T, T); */ + + case MINUS_EXPR: + if (TYPE_PTROB_P (type1) && TYPE_PTROB_P (type2)) + break; + if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2)) + { + type2 = ptrdiff_type_node; + break; + } + case MULT_EXPR: + case TRUNC_DIV_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + return candidates; + + case EQ_EXPR: + case NE_EXPR: + if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2)) + || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))) + break; + if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1)) + && null_ptr_cst_p (args[1])) + { + type2 = type1; + break; + } + if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)) + && null_ptr_cst_p (args[0])) + { + type1 = type2; + break; + } + case LT_EXPR: + case GT_EXPR: + case LE_EXPR: + case GE_EXPR: + case MAX_EXPR: + case MIN_EXPR: + if ((ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))) + break; + if (TYPE_PTR_P (type1) && null_ptr_cst_p (args[1])) + { + type2 = type1; + break; + } + if (null_ptr_cst_p (args[0]) && TYPE_PTR_P (type2)) + { + type1 = type2; + break; + } + return candidates; + + case PLUS_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + case ARRAY_REF: + if (INTEGRAL_TYPE_P (type1) && TYPE_PTROB_P (type2)) + { + type1 = ptrdiff_type_node; + break; + } + if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2)) + { + type2 = ptrdiff_type_node; + break; + } + return candidates; + +/* 18For every pair of promoted integral types L and R, there exist candi- + date operator functions of the form + LR operator%(L, R); + LR operator&(L, R); + LR operator^(L, R); + LR operator|(L, R); + L operator<<(L, R); + L operator>>(L, R); + where LR is the result of the usual arithmetic conversions between + types L and R. */ + + case TRUNC_MOD_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) + break; + return candidates; + +/* 19For every triple L, VQ, R), where L is an arithmetic or enumeration + type, VQ is either volatile or empty, and R is a promoted arithmetic + type, there exist candidate operator functions of the form + VQ L& operator=(VQ L&, R); + VQ L& operator*=(VQ L&, R); + VQ L& operator/=(VQ L&, R); + VQ L& operator+=(VQ L&, R); + VQ L& operator-=(VQ L&, R); + + 20For every pair T, VQ), where T is any type and VQ is either volatile + or empty, there exist candidate operator functions of the form + T*VQ& operator=(T*VQ&, T*); + + 21For every pair T, VQ), where T is a pointer to member type and VQ is + either volatile or empty, there exist candidate operator functions of + the form + VQ T& operator=(VQ T&, T); + + 22For every triple T, VQ, I), where T is a cv-qualified or cv- + unqualified complete object type, VQ is either volatile or empty, and + I is a promoted integral type, there exist candidate operator func- + tions of the form + T*VQ& operator+=(T*VQ&, I); + T*VQ& operator-=(T*VQ&, I); + + 23For every triple L, VQ, R), where L is an integral or enumeration + type, VQ is either volatile or empty, and R is a promoted integral + type, there exist candidate operator functions of the form + + VQ L& operator%=(VQ L&, R); + VQ L& operator<<=(VQ L&, R); + VQ L& operator>>=(VQ L&, R); + VQ L& operator&=(VQ L&, R); + VQ L& operator^=(VQ L&, R); + VQ L& operator|=(VQ L&, R); */ + + case MODIFY_EXPR: + switch (code2) + { + case PLUS_EXPR: + case MINUS_EXPR: + if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2)) + { + type2 = ptrdiff_type_node; + break; + } + case MULT_EXPR: + case TRUNC_DIV_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + return candidates; + + case TRUNC_MOD_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) + break; + return candidates; + + case NOP_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2)) + || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)) + || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)) + || ((TYPE_PTRMEMFUNC_P (type1) + || TREE_CODE (type1) == POINTER_TYPE) + && null_ptr_cst_p (args[1]))) + { + type2 = type1; + break; + } + return candidates; + + default: + my_friendly_abort (367); + } + type1 = build_reference_type (type1); + break; + + case COND_EXPR: + /* Kludge around broken overloading rules whereby + bool ? const char& : enum is ambiguous + (between int and const char&). */ + flags |= LOOKUP_NO_TEMP_BIND; + + /* Extension: Support ?: of enumeral type. Hopefully this will not + be an extension for long. */ + if (TREE_CODE (type1) == ENUMERAL_TYPE && type1 == type2) + break; + else if (TREE_CODE (type1) == ENUMERAL_TYPE + || TREE_CODE (type2) == ENUMERAL_TYPE) + return candidates; + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + if (TREE_CODE (type1) == TREE_CODE (type2) + && (TREE_CODE (type1) == REFERENCE_TYPE + || TREE_CODE (type1) == POINTER_TYPE + || TYPE_PTRMEMFUNC_P (type1) + || IS_AGGR_TYPE (type1))) + break; + if (TREE_CODE (type1) == REFERENCE_TYPE + || TREE_CODE (type2) == REFERENCE_TYPE) + return candidates; + if (((TYPE_PTRMEMFUNC_P (type1) || TREE_CODE (type1) == POINTER_TYPE) + && null_ptr_cst_p (args[1])) + || IS_AGGR_TYPE (type1)) + { + type2 = type1; + break; + } + if (((TYPE_PTRMEMFUNC_P (type2) || TREE_CODE (type2) == POINTER_TYPE) + && null_ptr_cst_p (args[0])) + || IS_AGGR_TYPE (type2)) + { + type1 = type2; + break; + } + return candidates; + + default: + my_friendly_abort (367); + } + + /* If we're dealing with two pointer types, we need candidates + for both of them. */ + if (type2 && type1 != type2 + && TREE_CODE (type1) == TREE_CODE (type2) + && (TREE_CODE (type1) == REFERENCE_TYPE + || (TREE_CODE (type1) == POINTER_TYPE + && TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2)) + || TYPE_PTRMEMFUNC_P (type1) + || IS_AGGR_TYPE (type1))) + { + candidates = build_builtin_candidate + (candidates, fnname, type1, type1, args, argtypes, flags); + return build_builtin_candidate + (candidates, fnname, type2, type2, args, argtypes, flags); + } + + return build_builtin_candidate + (candidates, fnname, type1, type2, args, argtypes, flags); +} + +tree +type_decays_to (type) + tree type; +{ + if (TREE_CODE (type) == ARRAY_TYPE) + return build_pointer_type (TREE_TYPE (type)); + if (TREE_CODE (type) == FUNCTION_TYPE) + return build_pointer_type (type); + return type; +} + +/* There are three conditions of builtin candidates: + + 1) bool-taking candidates. These are the same regardless of the input. + 2) pointer-pair taking candidates. These are generated for each type + one of the input types converts to. + 3) arithmetic candidates. According to the WP, we should generate + all of these, but I'm trying not to... */ + +static struct z_candidate * +add_builtin_candidates (candidates, code, code2, fnname, args, flags) + struct z_candidate *candidates; + enum tree_code code, code2; + tree fnname, *args; + int flags; +{ + int ref1, i; + tree type, argtypes[3], types[2]; + + for (i = 0; i < 3; ++i) + { + if (args[i]) + argtypes[i] = lvalue_type (args[i]); + else + argtypes[i] = NULL_TREE; + } + + switch (code) + { +/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type, + and VQ is either volatile or empty, there exist candidate operator + functions of the form + VQ T& operator++(VQ T&); */ + + case POSTINCREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case PREDECREMENT_EXPR: + case MODIFY_EXPR: + ref1 = 1; + break; + +/* 24There also exist candidate operator functions of the form + bool operator!(bool); + bool operator&&(bool, bool); + bool operator||(bool, bool); */ + + case TRUTH_NOT_EXPR: + return build_builtin_candidate + (candidates, fnname, boolean_type_node, + NULL_TREE, args, argtypes, flags); + + case TRUTH_ORIF_EXPR: + case TRUTH_ANDIF_EXPR: + return build_builtin_candidate + (candidates, fnname, boolean_type_node, + boolean_type_node, args, argtypes, flags); + + case ADDR_EXPR: + case COMPOUND_EXPR: + case COMPONENT_REF: + return candidates; + + default: + ref1 = 0; + } + + types[0] = types[1] = NULL_TREE; + + for (i = 0; i < 2; ++i) + { + if (! args[i]) + ; + else if (IS_AGGR_TYPE (argtypes[i])) + { + tree convs; + + if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR) + return candidates; + + convs = lookup_conversions (argtypes[i]); + + if (code == COND_EXPR) + { + if (real_lvalue_p (args[i])) + types[i] = scratch_tree_cons + (NULL_TREE, build_reference_type (argtypes[i]), types[i]); + + types[i] = scratch_tree_cons + (NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]); + } + + else if (! convs) + return candidates; + + for (; convs; convs = TREE_CHAIN (convs)) + { + type = TREE_TYPE (TREE_TYPE (OVL_CURRENT (TREE_VALUE (convs)))); + + if (i == 0 && ref1 + && (TREE_CODE (type) != REFERENCE_TYPE + || CP_TYPE_CONST_P (TREE_TYPE (type)))) + continue; + + if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE) + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); + + type = non_reference (type); + if (i != 0 || ! ref1) + { + type = TYPE_MAIN_VARIANT (type_decays_to (type)); + if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE) + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); + if (INTEGRAL_TYPE_P (type)) + type = type_promotes_to (type); + } + + if (! value_member (type, types[i])) + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); + } + } + else + { + if (code == COND_EXPR && real_lvalue_p (args[i])) + types[i] = scratch_tree_cons + (NULL_TREE, build_reference_type (argtypes[i]), types[i]); + type = non_reference (argtypes[i]); + if (i != 0 || ! ref1) + { + type = TYPE_MAIN_VARIANT (type_decays_to (type)); + if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE) + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); + if (INTEGRAL_TYPE_P (type)) + type = type_promotes_to (type); + } + types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); + } + } + + for (; types[0]; types[0] = TREE_CHAIN (types[0])) + { + if (types[1]) + for (type = types[1]; type; type = TREE_CHAIN (type)) + candidates = add_builtin_candidate + (candidates, code, code2, fnname, TREE_VALUE (types[0]), + TREE_VALUE (type), args, argtypes, flags); + else + candidates = add_builtin_candidate + (candidates, code, code2, fnname, TREE_VALUE (types[0]), + NULL_TREE, args, argtypes, flags); + } + + return candidates; +} + + +/* If TMPL can be successfully instantiated as indicated by + EXPLICIT_TARGS and ARGLIST, adds the instantiation to CANDIDATES. + + TMPL is the template. EXPLICIT_TARGS are any explicit template + arguments. ARGLIST is the arguments provided at the call-site. + The RETURN_TYPE is the desired type for conversion operators. If + OBJ is NULL_TREE, FLAGS are as for add_function_candidate. If an + OBJ is supplied, FLAGS are ignored, and OBJ is as for + add_conv_candidate. */ + +static struct z_candidate* +add_template_candidate_real (candidates, tmpl, explicit_targs, + arglist, return_type, flags, + obj, strict) + struct z_candidate *candidates; + tree tmpl, explicit_targs, arglist, return_type; + int flags; + tree obj; + unification_kind_t strict; +{ + int ntparms = DECL_NTPARMS (tmpl); + tree targs = make_scratch_vec (ntparms); + struct z_candidate *cand; + int i; + tree fn; + + i = fn_type_unification (tmpl, explicit_targs, targs, arglist, + return_type, strict); + + if (i != 0) + return candidates; + + fn = instantiate_template (tmpl, targs); + if (fn == error_mark_node) + return candidates; + + if (obj != NULL_TREE) + /* Aha, this is a conversion function. */ + cand = add_conv_candidate (candidates, fn, obj, arglist); + else + cand = add_function_candidate (candidates, fn, arglist, flags); + if (DECL_TI_TEMPLATE (fn) != tmpl) + /* This situation can occur if a member template of a template + class is specialized. Then, instantiate_template might return + an instantiation of the specialization, in which case the + DECL_TI_TEMPLATE field will point at the original + specialization. For example: + + template struct S { template void f(U); + template <> void f(int) {}; }; + S sd; + sd.f(3); + + Here, TMPL will be template S::f(U). + And, instantiate template will give us the specialization + template <> S::f(int). But, the DECL_TI_TEMPLATE field + for this will point at template template <> S::f(int), + so that we can find the definition. For the purposes of + overload resolution, however, we want the original TMPL. */ + cand->template = tree_cons (tmpl, targs, NULL_TREE); + else + cand->template = DECL_TEMPLATE_INFO (fn); + + return cand; +} + + +static struct z_candidate * +add_template_candidate (candidates, tmpl, explicit_targs, + arglist, return_type, flags, strict) + struct z_candidate *candidates; + tree tmpl, explicit_targs, arglist, return_type; + int flags; + unification_kind_t strict; +{ + return + add_template_candidate_real (candidates, tmpl, explicit_targs, + arglist, return_type, flags, + NULL_TREE, strict); +} + + +static struct z_candidate * +add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type) + struct z_candidate *candidates; + tree tmpl, obj, arglist, return_type; +{ + return + add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist, + return_type, 0, obj, DEDUCE_CONV); +} + + +static int +any_viable (cands) + struct z_candidate *cands; +{ + for (; cands; cands = cands->next) + if (pedantic ? cands->viable == 1 : cands->viable) + return 1; + return 0; +} + +static struct z_candidate * +splice_viable (cands) + struct z_candidate *cands; +{ + struct z_candidate **p = &cands; + + for (; *p; ) + { + if (pedantic ? (*p)->viable == 1 : (*p)->viable) + p = &((*p)->next); + else + *p = (*p)->next; + } + + return cands; +} + +static tree +build_this (obj) + tree obj; +{ + /* Fix this to work on non-lvalues. */ + if (IS_SIGNATURE_POINTER (TREE_TYPE (obj)) + || IS_SIGNATURE_REFERENCE (TREE_TYPE (obj))) + return obj; + else + return build_unary_op (ADDR_EXPR, obj, 0); +} + +static void +print_z_candidates (candidates) + struct z_candidate *candidates; +{ + const char *str = "candidates are:"; + for (; candidates; candidates = candidates->next) + { + if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE) + { + if (candidates->fn == ansi_opname [COND_EXPR]) + cp_error ("%s %D(%T, %T, %T) ", str, candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2))); + else if (TREE_VEC_LENGTH (candidates->convs) == 2) + cp_error ("%s %D(%T, %T) ", str, candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1))); + else + cp_error ("%s %D(%T) ", str, candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0))); + } + else if (TYPE_P (candidates->fn)) + cp_error ("%s %T ", str, candidates->fn); + else + cp_error_at ("%s %+#D%s", str, candidates->fn, + candidates->viable == -1 ? " " : ""); + str = " "; + } +} + +/* Returns the best overload candidate to perform the requested + conversion. This function is used for three the overloading situations + described in [over.match.copy], [over.match.conv], and [over.match.ref]. + If TOTYPE is a REFERENCE_TYPE, we're trying to find an lvalue binding as + per [dcl.init.ref], so we ignore temporary bindings. */ + +static struct z_candidate * +build_user_type_conversion_1 (totype, expr, flags) + tree totype, expr; + int flags; +{ + struct z_candidate *candidates, *cand; + tree fromtype = TREE_TYPE (expr); + tree ctors = NULL_TREE, convs = NULL_TREE, *p; + tree args = NULL_TREE; + tree templates = NULL_TREE; + + if (IS_AGGR_TYPE (totype)) + ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0); + if (IS_AGGR_TYPE (fromtype) + && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype))) + convs = lookup_conversions (fromtype); + + candidates = 0; + flags |= LOOKUP_NO_CONVERSION; + + if (ctors) + { + tree t = build_int_2 (0, 0); + TREE_TYPE (t) = build_pointer_type (totype); + args = build_scratch_list (NULL_TREE, expr); + if (TYPE_USES_PVBASES (totype) && !flag_vtable_thunks_compat) + { + args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); + flags |= LOOKUP_HAS_VLIST; + } + if (TYPE_USES_VIRTUAL_BASECLASSES (totype)) + args = scratch_tree_cons (NULL_TREE, integer_one_node, args); + args = scratch_tree_cons (NULL_TREE, t, args); + + ctors = TREE_VALUE (ctors); + } + for (; ctors; ctors = OVL_NEXT (ctors)) + { + tree ctor = OVL_CURRENT (ctors); + if (DECL_NONCONVERTING_P (ctor)) + continue; + + if (TREE_CODE (ctor) == TEMPLATE_DECL) + { + templates = scratch_tree_cons (NULL_TREE, ctor, templates); + candidates = + add_template_candidate (candidates, ctor, + NULL_TREE, args, NULL_TREE, flags, + DEDUCE_CALL); + } + else + candidates = add_function_candidate (candidates, ctor, + args, flags); + + if (candidates) + { + candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); + candidates->basetype_path = TYPE_BINFO (totype); + } + } + + if (convs) + args = build_scratch_list (NULL_TREE, build_this (expr)); + + for (; convs; convs = TREE_CHAIN (convs)) + { + tree fns = TREE_VALUE (convs); + int convflags = LOOKUP_NO_CONVERSION; + tree ics; + + /* If we are called to convert to a reference type, we are trying to + find an lvalue binding, so don't even consider temporaries. If + we don't find an lvalue binding, the caller will try again to + look for a temporary binding. */ + if (TREE_CODE (totype) == REFERENCE_TYPE) + convflags |= LOOKUP_NO_TEMP_BIND; + + if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL) + ics = implicit_conversion + (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags); + else + /* We can't compute this yet. */ + ics = error_mark_node; + + if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics)) + /* ignore the near match. */; + else if (ics) + for (; fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + struct z_candidate *old_candidates = candidates; + + if (TREE_CODE (fn) == TEMPLATE_DECL) + { + templates = scratch_tree_cons (NULL_TREE, fn, templates); + candidates = + add_template_candidate (candidates, fn, NULL_TREE, + args, totype, flags, + DEDUCE_CONV); + } + else + candidates = add_function_candidate (candidates, fn, + args, flags); + + if (candidates != old_candidates) + { + if (TREE_CODE (fn) == TEMPLATE_DECL) + ics = implicit_conversion + (totype, TREE_TYPE (TREE_TYPE (candidates->fn)), + 0, convflags); + + candidates->second_conv = ics; + candidates->basetype_path = TREE_PURPOSE (convs); + + if (ics == NULL_TREE) + candidates->viable = 0; + else if (candidates->viable == 1 && ICS_BAD_FLAG (ics)) + candidates->viable = -1; + } + } + } + + if (! any_viable (candidates)) + { +#if 0 + if (flags & LOOKUP_COMPLAIN) + { + if (candidates && ! candidates->next) + /* say why this one won't work or try to be loose */; + else + cp_error ("no viable candidates"); + } +#endif + + return 0; + } + + candidates = splice_viable (candidates); + cand = tourney (candidates); + + if (cand == 0) + { + if (flags & LOOKUP_COMPLAIN) + { + cp_error ("conversion from `%T' to `%T' is ambiguous", + fromtype, totype); + print_z_candidates (candidates); + } + + cand = candidates; /* any one will do */ + cand->second_conv = build1 (AMBIG_CONV, totype, expr); + ICS_USER_FLAG (cand->second_conv) = 1; + ICS_BAD_FLAG (cand->second_conv) = 1; + + return cand; + } + + for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; ) + p = &(TREE_OPERAND (*p, 0)); + + /* Pedantically, normal function declarations are never considered + to refer to template instantiations, so we only do this with + -fguiding-decls. */ + if (flag_guiding_decls && templates && ! cand->template + && !DECL_INITIAL (cand->fn) + && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE) + add_maybe_template (cand->fn, templates); + + *p = build + (USER_CONV, + (DECL_CONSTRUCTOR_P (cand->fn) + ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))), + expr, build_expr_ptr_wrapper (cand)); + ICS_USER_FLAG (cand->second_conv) = 1; + if (cand->viable == -1) + ICS_BAD_FLAG (cand->second_conv) = 1; + + return cand; +} + +tree +build_user_type_conversion (totype, expr, flags) + tree totype, expr; + int flags; +{ + struct z_candidate *cand + = build_user_type_conversion_1 (totype, expr, flags); + + if (cand) + { + if (TREE_CODE (cand->second_conv) == AMBIG_CONV) + return error_mark_node; + return convert_from_reference (convert_like (cand->second_conv, expr)); + } + return NULL_TREE; +} + +/* Do any initial processing on the arguments to a function call. */ + +static tree +resolve_args (args) + tree args; +{ + tree t; + for (t = args; t; t = TREE_CHAIN (t)) + { + if (TREE_VALUE (t) == error_mark_node) + return error_mark_node; + else if (TREE_CODE (TREE_TYPE (TREE_VALUE (t))) == VOID_TYPE) + { + error ("invalid use of void expression"); + return error_mark_node; + } + else if (TREE_CODE (TREE_VALUE (t)) == OFFSET_REF) + TREE_VALUE (t) = resolve_offset_ref (TREE_VALUE (t)); + } + return args; +} + +tree +build_new_function_call (fn, args) + tree fn, args; +{ + struct z_candidate *candidates = 0, *cand; + tree explicit_targs = NULL_TREE; + int template_only = 0; + + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) + { + explicit_targs = TREE_OPERAND (fn, 1); + fn = TREE_OPERAND (fn, 0); + template_only = 1; + } + + if (really_overloaded_fn (fn)) + { + tree t1; + tree templates = NULL_TREE; + + args = resolve_args (args); + + if (args == error_mark_node) + return error_mark_node; + + for (t1 = fn; t1; t1 = OVL_CHAIN (t1)) + { + tree t = OVL_FUNCTION (t1); + struct z_candidate *old_candidates = candidates; + + if (TREE_CODE (t) == TEMPLATE_DECL) + { + templates = scratch_tree_cons (NULL_TREE, t, templates); + candidates = add_template_candidate + (candidates, t, explicit_targs, args, NULL_TREE, + LOOKUP_NORMAL, DEDUCE_CALL); + } + else if (! template_only) + candidates = add_function_candidate + (candidates, t, args, LOOKUP_NORMAL); + + if (candidates != old_candidates) + candidates->basetype_path = DECL_REAL_CONTEXT (t); + } + + if (! any_viable (candidates)) + { + if (candidates && ! candidates->next) + return build_function_call (candidates->fn, args); + cp_error ("no matching function for call to `%D (%A)'", + DECL_NAME (OVL_FUNCTION (fn)), args); + if (candidates) + print_z_candidates (candidates); + return error_mark_node; + } + candidates = splice_viable (candidates); + cand = tourney (candidates); + + if (cand == 0) + { + cp_error ("call of overloaded `%D (%A)' is ambiguous", + DECL_NAME (OVL_FUNCTION (fn)), args); + print_z_candidates (candidates); + return error_mark_node; + } + + /* Pedantically, normal function declarations are never considered + to refer to template instantiations, so we only do this with + -fguiding-decls. */ + if (flag_guiding_decls && templates && ! cand->template + && ! DECL_INITIAL (cand->fn)) + add_maybe_template (cand->fn, templates); + + return build_over_call (cand, args, LOOKUP_NORMAL); + } + + /* This is not really overloaded. */ + fn = OVL_CURRENT (fn); + + return build_function_call (fn, args); +} + +static tree +build_object_call (obj, args) + tree obj, args; +{ + struct z_candidate *candidates = 0, *cand; + tree fns, convs, mem_args = NULL_TREE; + tree type = TREE_TYPE (obj); + + if (TYPE_PTRMEMFUNC_P (type)) + { + /* It's no good looking for an overloaded operator() on a + pointer-to-member-function. */ + cp_error ("pointer-to-member function %E cannot be called", obj); + cp_error ("without an object; consider using .* or ->*"); + return error_mark_node; + } + + fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 1); + if (fns == error_mark_node) + return error_mark_node; + + args = resolve_args (args); + + if (args == error_mark_node) + return error_mark_node; + + if (fns) + { + tree base = TREE_PURPOSE (fns); + mem_args = scratch_tree_cons (NULL_TREE, build_this (obj), args); + + for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + if (TREE_CODE (fn) == TEMPLATE_DECL) + { + candidates + = add_template_candidate (candidates, fn, NULL_TREE, + mem_args, NULL_TREE, + LOOKUP_NORMAL, DEDUCE_CALL); + } + else + candidates = add_function_candidate + (candidates, fn, mem_args, LOOKUP_NORMAL); + + if (candidates) + candidates->basetype_path = base; + } + } + + convs = lookup_conversions (type); + + for (; convs; convs = TREE_CHAIN (convs)) + { + tree fns = TREE_VALUE (convs); + tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))); + + if ((TREE_CODE (totype) == POINTER_TYPE + || TREE_CODE (totype) == REFERENCE_TYPE) + && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) + for (; fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + if (TREE_CODE (fn) == TEMPLATE_DECL) + { + candidates = add_template_conv_candidate (candidates, + fn, + obj, + args, + totype); + } + else + candidates = add_conv_candidate (candidates, fn, obj, args); + + if (candidates) + candidates->basetype_path = TREE_PURPOSE (convs); + } + } + + if (! any_viable (candidates)) + { + cp_error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args); + print_z_candidates (candidates); + return error_mark_node; + } + + candidates = splice_viable (candidates); + cand = tourney (candidates); + + if (cand == 0) + { + cp_error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args); + print_z_candidates (candidates); + return error_mark_node; + } + + /* Since cand->fn will be a type, not a function, for a conversion + function, we must be careful not to unconditionally look at + DECL_NAME here. */ + if (TREE_CODE (cand->fn) == FUNCTION_DECL + && DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR]) + return build_over_call (cand, mem_args, LOOKUP_NORMAL); + + obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj); + + /* FIXME */ + return build_function_call (obj, args); +} + +static void +op_error (code, code2, arg1, arg2, arg3, problem) + enum tree_code code, code2; + tree arg1, arg2, arg3; + const char *problem; +{ + const char * opname + = (code == MODIFY_EXPR ? assignop_tab [code2] : opname_tab [code]); + + switch (code) + { + case COND_EXPR: + cp_error ("%s for `%T ? %T : %T'", problem, + error_type (arg1), error_type (arg2), error_type (arg3)); + break; + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + cp_error ("%s for `%T%s'", problem, error_type (arg1), opname); + break; + case ARRAY_REF: + cp_error ("%s for `%T[%T]'", problem, + error_type (arg1), error_type (arg2)); + break; + default: + if (arg2) + cp_error ("%s for `%T %s %T'", problem, + error_type (arg1), opname, error_type (arg2)); + else + cp_error ("%s for `%s%T'", problem, opname, error_type (arg1)); + } +} + +tree +build_new_op (code, flags, arg1, arg2, arg3) + enum tree_code code; + int flags; + tree arg1, arg2, arg3; +{ + struct z_candidate *candidates = 0, *cand; + tree fns, mem_arglist = NULL_TREE, arglist, fnname; + enum tree_code code2 = NOP_EXPR; + tree templates = NULL_TREE; + tree conv; + + if (arg1 == error_mark_node + || arg2 == error_mark_node + || arg3 == error_mark_node) + return error_mark_node; + + /* This can happen if a template takes all non-type parameters, e.g. + undeclared_template<1, 5, 72>a; */ + if (code == LT_EXPR && TREE_CODE (arg1) == TEMPLATE_DECL) + { + cp_error ("`%D' must be declared before use", arg1); + return error_mark_node; + } + + if (code == MODIFY_EXPR) + { + code2 = TREE_CODE (arg3); + arg3 = NULL_TREE; + fnname = ansi_assopname[code2]; + } + else + fnname = ansi_opname[code]; + + switch (code) + { + case NEW_EXPR: + case VEC_NEW_EXPR: + case VEC_DELETE_EXPR: + case DELETE_EXPR: + /* Use build_op_new_call and build_op_delete_call instead. */ + my_friendly_abort (981018); + + case CALL_EXPR: + return build_object_call (arg1, arg2); + + default: + break; + } + + /* The comma operator can have void args. */ + if (TREE_CODE (arg1) == OFFSET_REF) + arg1 = resolve_offset_ref (arg1); + if (arg2 && TREE_CODE (arg2) == OFFSET_REF) + arg2 = resolve_offset_ref (arg2); + if (arg3 && TREE_CODE (arg3) == OFFSET_REF) + arg3 = resolve_offset_ref (arg3); + + if (code == COND_EXPR) + { + if (arg2 == NULL_TREE + || TREE_CODE (TREE_TYPE (arg2)) == VOID_TYPE + || TREE_CODE (TREE_TYPE (arg3)) == VOID_TYPE + || (! IS_OVERLOAD_TYPE (TREE_TYPE (arg2)) + && ! IS_OVERLOAD_TYPE (TREE_TYPE (arg3)))) + goto builtin; + } + else if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1)) + && (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2)))) + goto builtin; + + if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) + arg2 = integer_zero_node; + + if (arg2 && arg3) + arglist = scratch_tree_cons (NULL_TREE, arg1, scratch_tree_cons + (NULL_TREE, arg2, build_scratch_list (NULL_TREE, arg3))); + else if (arg2) + arglist = scratch_tree_cons (NULL_TREE, arg1, build_scratch_list (NULL_TREE, arg2)); + else + arglist = build_scratch_list (NULL_TREE, arg1); + + fns = lookup_function_nonclass (fnname, arglist); + + if (fns && TREE_CODE (fns) == TREE_LIST) + fns = TREE_VALUE (fns); + for (; fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + if (TREE_CODE (fn) == TEMPLATE_DECL) + { + templates = scratch_tree_cons (NULL_TREE, fn, templates); + candidates + = add_template_candidate (candidates, fn, NULL_TREE, + arglist, TREE_TYPE (fnname), + flags, DEDUCE_CALL); + } + else + candidates = add_function_candidate (candidates, fn, arglist, flags); + } + + if (IS_AGGR_TYPE (TREE_TYPE (arg1))) + { + fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 1); + if (fns == error_mark_node) + return fns; + } + else + fns = NULL_TREE; + + if (fns) + { + tree basetype = TREE_PURPOSE (fns); + mem_arglist = scratch_tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist)); + for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + tree this_arglist; + + if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) + this_arglist = mem_arglist; + else + this_arglist = arglist; + + if (TREE_CODE (fn) == TEMPLATE_DECL) + { + /* A member template. */ + templates = scratch_tree_cons (NULL_TREE, fn, templates); + candidates + = add_template_candidate (candidates, fn, NULL_TREE, + this_arglist, TREE_TYPE (fnname), + flags, DEDUCE_CALL); + } + else + candidates = add_function_candidate + (candidates, fn, this_arglist, flags); + + if (candidates) + candidates->basetype_path = basetype; + } + } + + { + tree args[3]; + + /* Rearrange the arguments for ?: so that add_builtin_candidate only has + to know about two args; a builtin candidate will always have a first + parameter of type bool. We'll handle that in + build_builtin_candidate. */ + if (code == COND_EXPR) + { + args[0] = arg2; + args[1] = arg3; + args[2] = arg1; + } + else + { + args[0] = arg1; + args[1] = arg2; + args[2] = NULL_TREE; + } + + candidates = add_builtin_candidates + (candidates, code, code2, fnname, args, flags); + } + + if (! any_viable (candidates)) + { + switch (code) + { + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + /* Look for an `operator++ (int)'. If they didn't have + one, then we fall back to the old way of doing things. */ + if (flags & LOOKUP_COMPLAIN) + cp_pedwarn ("no `%D (int)' declared for postfix `%s', trying prefix operator instead", + fnname, opname_tab [code]); + if (code == POSTINCREMENT_EXPR) + code = PREINCREMENT_EXPR; + else + code = PREDECREMENT_EXPR; + return build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE); + + /* The caller will deal with these. */ + case ADDR_EXPR: + case COMPOUND_EXPR: + case COMPONENT_REF: + return NULL_TREE; + + default: + break; + } + if (flags & LOOKUP_COMPLAIN) + { + op_error (code, code2, arg1, arg2, arg3, "no match"); + print_z_candidates (candidates); + } + return error_mark_node; + } + candidates = splice_viable (candidates); + cand = tourney (candidates); + + if (cand == 0) + { + if (flags & LOOKUP_COMPLAIN) + { + op_error (code, code2, arg1, arg2, arg3, "ambiguous overload"); + print_z_candidates (candidates); + } + return error_mark_node; + } + + if (TREE_CODE (cand->fn) == FUNCTION_DECL) + { + extern int warn_synth; + if (warn_synth + && fnname == ansi_opname[MODIFY_EXPR] + && DECL_ARTIFICIAL (cand->fn) + && candidates->next + && ! candidates->next->next) + { + cp_warning ("using synthesized `%#D' for copy assignment", + cand->fn); + cp_warning_at (" where cfront would use `%#D'", + cand == candidates + ? candidates->next->fn + : candidates->fn); + } + + /* Pedantically, normal function declarations are never considered + to refer to template instantiations, so we only do this with + -fguiding-decls. */ + if (flag_guiding_decls && templates && ! cand->template + && ! DECL_INITIAL (cand->fn) + && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE) + add_maybe_template (cand->fn, templates); + + return build_over_call + (cand, + TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE + ? mem_arglist : arglist, + LOOKUP_NORMAL); + } + + /* Check for comparison of different enum types. */ + switch (code) + { + case GT_EXPR: + case LT_EXPR: + case GE_EXPR: + case LE_EXPR: + case EQ_EXPR: + case NE_EXPR: + if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE + && TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE + && (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) + != TYPE_MAIN_VARIANT (TREE_TYPE (arg2)))) + { + cp_warning ("comparison between `%#T' and `%#T'", + TREE_TYPE (arg1), TREE_TYPE (arg2)); + } + break; + default: + break; + } + + /* We need to strip any leading REF_BIND so that bitfields don't cause + errors. This should not remove any important conversions, because + builtins don't apply to class objects directly. */ + conv = TREE_VEC_ELT (cand->convs, 0); + if (TREE_CODE (conv) == REF_BIND) + conv = TREE_OPERAND (conv, 0); + arg1 = convert_like (conv, arg1); + if (arg2) + { + conv = TREE_VEC_ELT (cand->convs, 1); + if (TREE_CODE (conv) == REF_BIND) + conv = TREE_OPERAND (conv, 0); + arg2 = convert_like (conv, arg2); + } + if (arg3) + { + conv = TREE_VEC_ELT (cand->convs, 2); + if (TREE_CODE (conv) == REF_BIND) + conv = TREE_OPERAND (conv, 0); + arg3 = convert_like (conv, arg3); + } + +builtin: + switch (code) + { + case MODIFY_EXPR: + return build_modify_expr (arg1, code2, arg2); + + case INDIRECT_REF: + return build_indirect_ref (arg1, "unary *"); + + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case GT_EXPR: + case LT_EXPR: + case GE_EXPR: + case LE_EXPR: + case EQ_EXPR: + case NE_EXPR: + case MAX_EXPR: + case MIN_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case TRUNC_MOD_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + return build_binary_op_nodefault (code, arg1, arg2, code); + + case CONVERT_EXPR: + case NEGATE_EXPR: + case BIT_NOT_EXPR: + case TRUTH_NOT_EXPR: + case PREINCREMENT_EXPR: + case POSTINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTDECREMENT_EXPR: + case REALPART_EXPR: + case IMAGPART_EXPR: + return build_unary_op (code, arg1, candidates != 0); + + case ARRAY_REF: + return build_array_ref (arg1, arg2); + + case COND_EXPR: + return build_conditional_expr (arg1, arg2, arg3); + + case MEMBER_REF: + return build_m_component_ref + (build_indirect_ref (arg1, NULL_PTR), arg2); + + /* The caller will deal with these. */ + case ADDR_EXPR: + case COMPONENT_REF: + case COMPOUND_EXPR: + return NULL_TREE; + + default: + my_friendly_abort (367); + return NULL_TREE; + } +} + +/* Build up a call to operator new. This has to be handled differently + from other operators in the way lookup is handled; first members are + considered, then globals. CODE is either NEW_EXPR or VEC_NEW_EXPR. + TYPE is the type to be created. ARGS are any new-placement args. + FLAGS are the usual overloading flags. */ + +tree +build_op_new_call (code, type, args, flags) + enum tree_code code; + tree type, args; + int flags; +{ + tree fnname = ansi_opname[code]; + + if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL) + && (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR)))) + { + return build_method_call (build_dummy_object (type), + fnname, args, NULL_TREE, flags); + } + else + return build_new_function_call + (lookup_function_nonclass (fnname, args), args); +} + +/* Build a call to operator delete. This has to be handled very specially, + because the restrictions on what signatures match are different from all + other call instances. For a normal delete, only a delete taking (void *) + or (void *, size_t) is accepted. For a placement delete, only an exact + match with the placement new is accepted. + + CODE is either DELETE_EXPR or VEC_DELETE_EXPR. + ADDR is the pointer to be deleted. For placement delete, it is also + used to determine what the corresponding new looked like. + SIZE is the size of the memory block to be deleted. + FLAGS are the usual overloading flags. + PLACEMENT is the corresponding placement new call, or 0. */ + +tree +build_op_delete_call (code, addr, size, flags, placement) + enum tree_code code; + tree addr, size, placement; + int flags; +{ + tree fn, fns, fnname, fntype, argtypes, args, type; + + if (addr == error_mark_node) + return error_mark_node; + + type = TREE_TYPE (TREE_TYPE (addr)); + fnname = ansi_opname[code]; + + if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)) + /* In [class.free] + + If the result of the lookup is ambiguous or inaccessible, or if + the lookup selects a placement deallocation function, the + program is ill-formed. + + Therefore, we ask lookup_fnfields to complain ambout ambiguity. */ + { + fns = lookup_fnfields (TYPE_BINFO (type), fnname, 1); + if (fns == error_mark_node) + return error_mark_node; + } + else + fns = NULL_TREE; + + if (fns == NULL_TREE) + fns = lookup_name_nonclass (fnname); + + if (placement) + { + /* placement is a CALL_EXPR around an ADDR_EXPR around a function. */ + + /* Extract the function. */ + argtypes = TREE_OPERAND (TREE_OPERAND (placement, 0), 0); + /* Then the second parm type. */ + argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes))); + + /* Also the second argument. */ + args = TREE_CHAIN (TREE_OPERAND (placement, 1)); + } + else + { + /* First try it without the size argument. */ + argtypes = void_list_node; + args = NULL_TREE; + } + + argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes); + fntype = build_function_type (void_type_node, argtypes); + + /* Strip const and volatile from addr. */ + if (type != TYPE_MAIN_VARIANT (type)) + addr = cp_convert (build_pointer_type (TYPE_MAIN_VARIANT (type)), addr); + + fn = instantiate_type (fntype, fns, 2); + + if (fn != error_mark_node) + { + if (TREE_CODE (fns) == TREE_LIST) + /* Member functions. */ + enforce_access (TREE_PURPOSE (fns), fn); + return build_function_call (fn, expr_tree_cons (NULL_TREE, addr, args)); + } + + /* If we are doing placement delete we do nothing if we don't find a + matching op delete. */ + if (placement) + return NULL_TREE; + + /* Normal delete; now try to find a match including the size argument. */ + argtypes = tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, sizetype, void_list_node)); + fntype = build_function_type (void_type_node, argtypes); + + fn = instantiate_type (fntype, fns, 2); + + if (fn != error_mark_node) + { + if (BASELINK_P (fns)) + /* Member functions. */ + enforce_access (TREE_PURPOSE (fns), fn); + return build_function_call + (fn, expr_tree_cons (NULL_TREE, addr, + build_expr_list (NULL_TREE, size))); + } + + /* finish_function passes LOOKUP_SPECULATIVELY if we're in a + destructor, in which case the error should be deferred + until someone actually tries to delete one of these. */ + if (flags & LOOKUP_SPECULATIVELY) + return NULL_TREE; + + cp_error ("no suitable operator delete for `%T'", type); + return error_mark_node; +} + +/* If the current scope isn't allowed to access DECL along + BASETYPE_PATH, give an error. The most derived class in + BASETYPE_PATH is the one used to qualify DECL. */ + +int +enforce_access (basetype_path, decl) + tree basetype_path; + tree decl; +{ + int accessible; + + accessible = accessible_p (basetype_path, decl); + if (!accessible) + { + if (TREE_PRIVATE (decl)) + cp_error_at ("`%+#D' is private", decl); + else if (TREE_PROTECTED (decl)) + cp_error_at ("`%+#D' is protected", decl); + else + cp_error_at ("`%+#D' is inaccessible", decl); + cp_error ("within this context"); + return 0; + } + + return 1; +} + +/* Perform the conversions in CONVS on the expression EXPR. */ + +static tree +convert_like (convs, expr) + tree convs, expr; +{ + if (ICS_BAD_FLAG (convs) + && TREE_CODE (convs) != USER_CONV + && TREE_CODE (convs) != AMBIG_CONV) + { + tree t = convs; + for (; t; t = TREE_OPERAND (t, 0)) + { + if (TREE_CODE (t) == USER_CONV) + { + expr = convert_like (t, expr); + break; + } + else if (TREE_CODE (t) == AMBIG_CONV) + return convert_like (t, expr); + else if (TREE_CODE (t) == IDENTITY_CONV) + break; + } + return convert_for_initialization + (NULL_TREE, TREE_TYPE (convs), expr, LOOKUP_NORMAL, + "conversion", NULL_TREE, 0); + } + + switch (TREE_CODE (convs)) + { + case USER_CONV: + { + struct z_candidate *cand + = WRAPPER_PTR (TREE_OPERAND (convs, 1)); + tree fn = cand->fn; + tree args; + int flags = LOOKUP_NORMAL; + + if (DECL_CONSTRUCTOR_P (fn)) + { + tree t = build_int_2 (0, 0); + TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn)); + + args = build_scratch_list (NULL_TREE, expr); + if (TYPE_USES_PVBASES (DECL_CONTEXT (fn)) + && !flag_vtable_thunks_compat) + { + args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); + flags != LOOKUP_HAS_VLIST; + } + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) + args = scratch_tree_cons (NULL_TREE, integer_one_node, args); + args = scratch_tree_cons (NULL_TREE, t, args); + } + else + args = build_this (expr); + expr = build_over_call (cand, args, flags); + + /* If this is a constructor or a function returning an aggr type, + we need to build up a TARGET_EXPR. */ + if (DECL_CONSTRUCTOR_P (fn)) + expr = build_cplus_new (TREE_TYPE (convs), expr); + + return expr; + } + case IDENTITY_CONV: + if (type_unknown_p (expr)) + expr = instantiate_type (TREE_TYPE (convs), expr, 1); + if (TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); + return expr; + case AMBIG_CONV: + /* Call build_user_type_conversion again for the error. */ + return build_user_type_conversion + (TREE_TYPE (convs), TREE_OPERAND (convs, 0), LOOKUP_NORMAL); + + default: + break; + }; + + expr = convert_like (TREE_OPERAND (convs, 0), expr); + if (expr == error_mark_node) + return error_mark_node; + + switch (TREE_CODE (convs)) + { + case RVALUE_CONV: + if (! IS_AGGR_TYPE (TREE_TYPE (convs))) + return expr; + /* else fall through */ + case BASE_CONV: + { + tree cvt_expr = build_user_type_conversion + (TREE_TYPE (convs), expr, LOOKUP_NORMAL); + if (!cvt_expr) + { + /* This can occur if, for example, the EXPR has incomplete + type. We can't check for that before attempting the + conversion because the type might be an incomplete + array type, which is OK if some constructor for the + destination type takes a pointer argument. */ + if (TYPE_SIZE (TREE_TYPE (expr)) == 0) + { + if (same_type_p (TREE_TYPE (expr), TREE_TYPE (convs))) + incomplete_type_error (expr, TREE_TYPE (expr)); + else + cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'", + expr, TREE_TYPE (expr), TREE_TYPE (convs)); + } + else + cp_error ("could not convert `%E' to `%T'", + expr, TREE_TYPE (convs)); + return error_mark_node; + } + return cvt_expr; + } + + case REF_BIND: + return convert_to_reference + (TREE_TYPE (convs), expr, + CONV_IMPLICIT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION, + error_mark_node); + case LVALUE_CONV: + return decay_conversion (expr); + + case QUAL_CONV: + /* Warn about deprecated conversion if appropriate. */ + string_conv_p (TREE_TYPE (convs), expr, 1); + break; + + default: + break; + } + return ocp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT, + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); +} + +/* ARG is being passed to a varargs function. Perform any conversions + required. Return the converted value. */ + +tree +convert_arg_to_ellipsis (arg) + tree arg; +{ + if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE + && (TYPE_PRECISION (TREE_TYPE (arg)) + < TYPE_PRECISION (double_type_node))) + /* Convert `float' to `double'. */ + arg = cp_convert (double_type_node, arg); + else if (IS_AGGR_TYPE (TREE_TYPE (arg)) + && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (arg))) + cp_warning ("cannot pass objects of type `%T' through `...'", + TREE_TYPE (arg)); + else + /* Convert `short' and `char' to full-size `int'. */ + arg = default_conversion (arg); + + arg = require_complete_type (arg); + + return arg; +} + +/* ARG is a default argument expression being passed to a parameter of + the indicated TYPE, which is a parameter to FN. Do any required + conversions. Return the converted value. */ + +tree +convert_default_arg (type, arg, fn) + tree type; + tree arg; + tree fn; +{ + if (fn && DECL_TEMPLATE_INFO (fn)) + { + /* This default argument came from a template. Instantiate the + default argument here, not in tsubst. In the case of + something like: + + template + struct S { + static T t(); + void f(T = t()); + }; + + we must be careful to do name lookup in the scope of S, + rather than in the current class. */ + if (DECL_CLASS_SCOPE_P (fn)) + pushclass (DECL_REAL_CONTEXT (fn), 2); + + arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE); + + if (DECL_CLASS_SCOPE_P (fn)) + popclass (); + + /* Make sure the default argument is reasonable. */ + arg = check_default_argument (type, arg); + } + + arg = break_out_target_exprs (arg); + + if (TREE_CODE (arg) == CONSTRUCTOR) + { + arg = digest_init (type, arg, 0); + arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, + "default argument", 0, 0); + } + else + { + /* This could get clobbered by the following call. */ + if (TREE_HAS_CONSTRUCTOR (arg)) + arg = copy_node (arg); + + arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, + "default argument", 0, 0); +#ifdef PROMOTE_PROTOTYPES + if ((TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) + arg = default_conversion (arg); +#endif + } + + return arg; +} + +static tree +build_over_call (cand, args, flags) + struct z_candidate *cand; + tree args; + int flags; +{ + tree fn = cand->fn; + tree convs = cand->convs; + tree converted_args = NULL_TREE; + tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); + tree conv, arg, val; + int i = 0; + int is_method = 0; + + /* Give any warnings we noticed during overload resolution. */ + if (cand->warnings) + for (val = cand->warnings; val; val = TREE_CHAIN (val)) + joust (cand, WRAPPER_PTR (TREE_VALUE (val)), 1); + + if (DECL_FUNCTION_MEMBER_P (fn)) + enforce_access (cand->basetype_path, fn); + + if (args && TREE_CODE (args) != TREE_LIST) + args = build_scratch_list (NULL_TREE, args); + arg = args; + + /* The implicit parameters to a constructor are not considered by overload + resolution, and must be of the proper type. */ + if (DECL_CONSTRUCTOR_P (fn)) + { + converted_args = expr_tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args); + arg = TREE_CHAIN (arg); + parm = TREE_CHAIN (parm); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) + { + converted_args = expr_tree_cons + (NULL_TREE, TREE_VALUE (arg), converted_args); + arg = TREE_CHAIN (arg); + parm = TREE_CHAIN (parm); + } + if (flags & LOOKUP_HAS_VLIST) + { + converted_args = expr_tree_cons + (NULL_TREE, TREE_VALUE (arg), converted_args); + arg = TREE_CHAIN (arg); + parm = TREE_CHAIN (parm); + } + } + /* Bypass access control for 'this' parameter. */ + else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) + { + tree parmtype = TREE_VALUE (parm); + tree argtype = TREE_TYPE (TREE_VALUE (arg)); + tree t; + if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i))) + cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers", + TREE_TYPE (argtype), fn); + + /* [class.mfct.nonstatic]: If a nonstatic member function of a class + X is called for an object that is not of type X, or of a type + derived from X, the behavior is undefined. + + So we can assume that anything passed as 'this' is non-null, and + optimize accordingly. */ + if (TREE_CODE (parmtype) == POINTER_TYPE) + t = convert_pointer_to_real (TREE_TYPE (parmtype), TREE_VALUE (arg)); + else + /* This happens with signatures. */ + t = convert_force (parmtype, TREE_VALUE (arg), CONV_C_CAST); + converted_args = expr_tree_cons (NULL_TREE, t, converted_args); + parm = TREE_CHAIN (parm); + arg = TREE_CHAIN (arg); + ++i; + is_method = 1; + } + + for (; arg && parm; + parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i) + { + tree type = TREE_VALUE (parm); + + conv = TREE_VEC_ELT (convs, i); + if (ICS_BAD_FLAG (conv)) + { + tree t = conv; + val = TREE_VALUE (arg); + + for (; t; t = TREE_OPERAND (t, 0)) + { + if (TREE_CODE (t) == USER_CONV + || TREE_CODE (t) == AMBIG_CONV) + { + val = convert_like (t, val); + break; + } + else if (TREE_CODE (t) == IDENTITY_CONV) + break; + } + val = convert_for_initialization + (NULL_TREE, type, val, LOOKUP_NORMAL, + "argument passing", fn, i - is_method); + } + else + { + /* Issue warnings about peculiar, but legal, uses of NULL. */ + if (ARITHMETIC_TYPE_P (TREE_VALUE (parm)) + && TREE_VALUE (arg) == null_node) + cp_warning ("converting NULL to non-pointer type"); + + val = convert_like (conv, TREE_VALUE (arg)); + } + +#ifdef PROMOTE_PROTOTYPES + if ((TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) + val = default_conversion (val); +#endif + converted_args = expr_tree_cons (NULL_TREE, val, converted_args); + } + + /* Default arguments */ + for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm)) + converted_args + = expr_tree_cons (NULL_TREE, + convert_default_arg (TREE_VALUE (parm), + TREE_PURPOSE (parm), + fn), + converted_args); + + /* Ellipsis */ + for (; arg; arg = TREE_CHAIN (arg)) + converted_args + = expr_tree_cons (NULL_TREE, + convert_arg_to_ellipsis (TREE_VALUE (arg)), + converted_args); + + converted_args = nreverse (converted_args); + + if (warn_format && (DECL_NAME (fn) || DECL_ASSEMBLER_NAME (fn))) + check_function_format (DECL_NAME (fn), DECL_ASSEMBLER_NAME (fn), + converted_args); + + /* Avoid actually calling copy constructors and copy assignment operators, + if possible. */ + + if (! flag_elide_constructors) + /* Do things the hard way. */; + else if (DECL_CONSTRUCTOR_P (fn) + && TREE_VEC_LENGTH (convs) == 1 + && copy_args_p (fn)) + { + tree targ; + arg = TREE_CHAIN (converted_args); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) + arg = TREE_CHAIN (arg); + if (flags & LOOKUP_HAS_VLIST) + arg = TREE_CHAIN (arg); + arg = TREE_VALUE (arg); + + /* Pull out the real argument, disregarding const-correctness. */ + targ = arg; + while (TREE_CODE (targ) == NOP_EXPR + || TREE_CODE (targ) == NON_LVALUE_EXPR + || TREE_CODE (targ) == CONVERT_EXPR) + targ = TREE_OPERAND (targ, 0); + if (TREE_CODE (targ) == ADDR_EXPR) + { + targ = TREE_OPERAND (targ, 0); + if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg))), + TYPE_MAIN_VARIANT (TREE_TYPE (targ)))) + targ = NULL_TREE; + } + else + targ = NULL_TREE; + + if (targ) + arg = targ; + else + arg = build_indirect_ref (arg, 0); + + /* [class.copy]: the copy constructor is implicitly defined even if + the implementation elided its use. */ + if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn))) + mark_used (fn); + + /* If we're creating a temp and we already have one, don't create a + new one. If we're not creating a temp but we get one, use + INIT_EXPR to collapse the temp into our target. Otherwise, if the + ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a + temp or an INIT_EXPR otherwise. */ + if (integer_zerop (TREE_VALUE (args))) + { + if (! real_lvalue_p (arg)) + return arg; + else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) + { + val = build_decl (VAR_DECL, NULL_TREE, DECL_CONTEXT (fn)); + val = build (TARGET_EXPR, DECL_CONTEXT (fn), val, arg, 0, 0); + TREE_SIDE_EFFECTS (val) = 1; + return val; + } + } + else if (! real_lvalue_p (arg) + || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) + { + tree address; + tree to = stabilize_reference + (build_indirect_ref (TREE_VALUE (args), 0)); + + /* If we're initializing an empty class, then we actually + have to use a MODIFY_EXPR rather than an INIT_EXPR. The + reason is that the dummy padding member in the target may + not actually be allocated if TO is a base class + subobject. Since we've set TYPE_NONCOPIED_PARTS on the + padding, a MODIFY_EXPR will preserve its value, which is + the right thing to do if it's not really padding at all. + + It's not safe to just throw away the ARG if we're looking + at an empty class because the ARG might contain a + TARGET_EXPR which wants to be bound to TO. If it is not, + expand_expr will assign a dummy slot for the TARGET_EXPR, + and we will call a destructor for it, which is wrong, + because we will also destroy TO, but will never have + constructed it. */ + val = build (is_empty_class (DECL_CLASS_CONTEXT (fn)) + ? MODIFY_EXPR : INIT_EXPR, + DECL_CONTEXT (fn), to, arg); + TREE_SIDE_EFFECTS (val) = 1; + address = build_unary_op (ADDR_EXPR, val, 0); + /* Avoid a warning about this expression, if the address is + never used. */ + TREE_USED (address) = 1; + return address; + } + } + else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR] + && copy_args_p (fn) + && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CLASS_CONTEXT (fn))) + { + tree to = stabilize_reference + (build_indirect_ref (TREE_VALUE (converted_args), 0)); + + arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0); + + val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg); + TREE_SIDE_EFFECTS (val) = 1; + return val; + } + + mark_used (fn); + + if (DECL_CLASS_SCOPE_P (fn) && IS_SIGNATURE (DECL_CONTEXT (fn))) + return build_signature_method_call (fn, converted_args); + else if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0) + { + tree t, *p = &TREE_VALUE (converted_args); + tree binfo = get_binfo + (DECL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0); + *p = convert_pointer_to_real (binfo, *p); + if (TREE_SIDE_EFFECTS (*p)) + *p = save_expr (*p); + t = build_pointer_type (TREE_TYPE (fn)); + fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn)); + TREE_TYPE (fn) = t; + } + else if (DECL_INLINE (fn)) + fn = inline_conversion (fn); + else + fn = build_addr_func (fn); + + /* Recognize certain built-in functions so we can make tree-codes + other than CALL_EXPR. We do this when it enables fold-const.c + to do something useful. */ + + if (TREE_CODE (fn) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL + && DECL_BUILT_IN (TREE_OPERAND (fn, 0))) + switch (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0))) + { + case BUILT_IN_ABS: + case BUILT_IN_LABS: + case BUILT_IN_FABS: + if (converted_args == 0) + return integer_zero_node; + return build_unary_op (ABS_EXPR, TREE_VALUE (converted_args), 0); + default: + break; + } + + fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args); + if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE) + return fn; + fn = require_complete_type (fn); + if (IS_AGGR_TYPE (TREE_TYPE (fn))) + fn = build_cplus_new (TREE_TYPE (fn), fn); + return convert_from_reference (fn); +} + +static tree +build_new_method_call (instance, name, args, basetype_path, flags) + tree instance, name, args, basetype_path; + int flags; +{ + struct z_candidate *candidates = 0, *cand; + tree explicit_targs = NULL_TREE; + tree basetype, mem_args = NULL_TREE, fns, instance_ptr; + tree pretty_name; + tree user_args = args; + tree templates = NULL_TREE; + int template_only = 0; + + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + explicit_targs = TREE_OPERAND (name, 1); + name = TREE_OPERAND (name, 0); + if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd') + name = DECL_NAME (name); + else + { + if (TREE_CODE (name) == COMPONENT_REF) + name = TREE_OPERAND (name, 1); + if (TREE_CODE (name) == OVERLOAD) + name = DECL_NAME (OVL_CURRENT (name)); + } + + template_only = 1; + } + + /* If there is an extra argument for controlling virtual bases, + remove it for error reporting. */ + if (flags & LOOKUP_HAS_IN_CHARGE) + user_args = TREE_CHAIN (args); + if (flags & LOOKUP_HAS_VLIST) + user_args = TREE_CHAIN (user_args); + + args = resolve_args (args); + + if (args == error_mark_node) + return error_mark_node; + + if (instance == NULL_TREE) + basetype = BINFO_TYPE (basetype_path); + else + { + if (TREE_CODE (instance) == OFFSET_REF) + instance = resolve_offset_ref (instance); + if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) + instance = convert_from_reference (instance); + basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance)); + + /* XXX this should be handled before we get here. */ + if (! IS_AGGR_TYPE (basetype) + && ! (TYPE_LANG_SPECIFIC (basetype) + && (IS_SIGNATURE_POINTER (basetype) + || IS_SIGNATURE_REFERENCE (basetype)))) + { + if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node) + cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", + name, instance, basetype); + + return error_mark_node; + } + + /* If `instance' is a signature pointer/reference and `name' is + not a constructor, we are calling a signature member function. + In that case set the `basetype' to the signature type. */ + if ((IS_SIGNATURE_POINTER (basetype) + || IS_SIGNATURE_REFERENCE (basetype)) + && TYPE_IDENTIFIER (basetype) != name) + basetype = SIGNATURE_TYPE (basetype); + } + + if (basetype_path == NULL_TREE) + basetype_path = TYPE_BINFO (basetype); + + if (instance) + { + instance_ptr = build_this (instance); + + if (! template_only) + { + /* XXX this should be handled before we get here. */ + fns = build_field_call (basetype_path, instance_ptr, name, args); + if (fns) + return fns; + } + } + else + { + instance_ptr = build_int_2 (0, 0); + TREE_TYPE (instance_ptr) = build_pointer_type (basetype); + } + + pretty_name + = (name == ctor_identifier ? constructor_name (basetype) : name); + + fns = lookup_fnfields (basetype_path, name, 1); + + if (fns == error_mark_node) + return error_mark_node; + if (fns) + { + tree fn = TREE_VALUE (fns); + if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype) + && ! (flags & LOOKUP_HAS_IN_CHARGE)) + { + if (TYPE_USES_PVBASES(basetype) + && (!flag_vtable_thunks_compat || (name == dtor_identifier))) + { + args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); + flags |= LOOKUP_HAS_VLIST; + } + flags |= LOOKUP_HAS_IN_CHARGE; + args = scratch_tree_cons (NULL_TREE, integer_one_node, args); + } + mem_args = scratch_tree_cons (NULL_TREE, instance_ptr, args); + for (; fn; fn = OVL_NEXT (fn)) + { + tree t = OVL_CURRENT (fn); + tree this_arglist; + + /* We can end up here for copy-init of same or base class. */ + if (name == ctor_identifier + && (flags & LOOKUP_ONLYCONVERTING) + && DECL_NONCONVERTING_P (t)) + continue; + if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE) + this_arglist = mem_args; + else + this_arglist = args; + + if (TREE_CODE (t) == TEMPLATE_DECL) + { + /* A member template. */ + templates = scratch_tree_cons (NULL_TREE, t, templates); + candidates = + add_template_candidate (candidates, t, explicit_targs, + this_arglist, + TREE_TYPE (name), flags, DEDUCE_CALL); + } + else if (! template_only) + candidates = add_function_candidate (candidates, t, + this_arglist, flags); + + if (candidates) + candidates->basetype_path = TREE_PURPOSE (fns); + } + } + + if (! any_viable (candidates)) + { + /* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */ + if (flags & LOOKUP_SPECULATIVELY) + return NULL_TREE; + if (TYPE_SIZE (basetype) == 0) + incomplete_type_error (instance_ptr, basetype); + else + cp_error ("no matching function for call to `%T::%D (%A)%V'", + basetype, pretty_name, user_args, + TREE_TYPE (TREE_TYPE (instance_ptr))); + print_z_candidates (candidates); + return error_mark_node; + } + candidates = splice_viable (candidates); + cand = tourney (candidates); + + if (cand == 0) + { + cp_error ("call of overloaded `%D(%A)' is ambiguous", pretty_name, + user_args); + print_z_candidates (candidates); + return error_mark_node; + } + + if (DECL_ABSTRACT_VIRTUAL_P (cand->fn) + && instance == current_class_ref + && DECL_CONSTRUCTOR_P (current_function_decl) + && ! (flags & LOOKUP_NONVIRTUAL) + && value_member (cand->fn, CLASSTYPE_ABSTRACT_VIRTUALS (basetype))) + cp_error ("abstract virtual `%#D' called from constructor", cand->fn); + if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE + && is_dummy_object (instance_ptr)) + { + cp_error ("cannot call member function `%D' without object", cand->fn); + return error_mark_node; + } + + if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL) + && ((instance == current_class_ref && (dtor_label || ctor_label)) + || resolves_to_fixed_type_p (instance, 0))) + flags |= LOOKUP_NONVIRTUAL; + + /* Pedantically, normal function declarations are never considered + to refer to template instantiations, so we only do this with + -fguiding-decls. */ + if (flag_guiding_decls && templates && ! cand->template + && ! DECL_INITIAL (cand->fn)) + add_maybe_template (cand->fn, templates); + + return build_over_call + (cand, + TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args, + flags); +} + +/* Returns non-zero iff standard conversion sequence ICS1 is a proper + subsequence of ICS2. */ + +static int +is_subseq (ics1, ics2) + tree ics1, ics2; +{ + /* We can assume that a conversion of the same code + between the same types indicates a subsequence since we only get + here if the types we are converting from are the same. */ + + while (TREE_CODE (ics1) == RVALUE_CONV + || TREE_CODE (ics1) == LVALUE_CONV) + ics1 = TREE_OPERAND (ics1, 0); + + while (1) + { + while (TREE_CODE (ics2) == RVALUE_CONV + || TREE_CODE (ics2) == LVALUE_CONV) + ics2 = TREE_OPERAND (ics2, 0); + + if (TREE_CODE (ics2) == USER_CONV + || TREE_CODE (ics2) == AMBIG_CONV + || TREE_CODE (ics2) == IDENTITY_CONV) + /* At this point, ICS1 cannot be a proper subsequence of + ICS2. We can get a USER_CONV when we are comparing the + second standard conversion sequence of two user conversion + sequences. */ + return 0; + + ics2 = TREE_OPERAND (ics2, 0); + + if (TREE_CODE (ics2) == TREE_CODE (ics1) + && same_type_p (TREE_TYPE (ics2), TREE_TYPE (ics1)) + && same_type_p (TREE_TYPE (TREE_OPERAND (ics2, 0)), + TREE_TYPE (TREE_OPERAND (ics1, 0)))) + return 1; + } +} + +/* Returns non-zero iff DERIVED is derived from BASE. The inputs may + be any _TYPE nodes. */ + +int +is_properly_derived_from (derived, base) + tree derived; + tree base; +{ + if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived)) + || !IS_AGGR_TYPE_CODE (TREE_CODE (base))) + return 0; + + /* We only allow proper derivation here. The DERIVED_FROM_P macro + considers every class derived from itself. */ + return (!same_type_p (TYPE_MAIN_VARIANT (derived), + TYPE_MAIN_VARIANT (base)) + && DERIVED_FROM_P (base, derived)); +} + +/* We build the ICS for an implicit object parameter as a pointer + conversion sequence. However, such a sequence should be compared + as if it were a reference conversion sequence. If ICS is the + implicit conversion sequence for an implicit object parameter, + modify it accordingly. */ + +static void +maybe_handle_implicit_object (ics) + tree* ics; +{ + if (ICS_THIS_FLAG (*ics)) + { + /* [over.match.funcs] + + For non-static member functions, the type of the + implicit object parameter is "reference to cv X" + where X is the class of which the function is a + member and cv is the cv-qualification on the member + function declaration. */ + tree t = *ics; + if (TREE_CODE (t) == QUAL_CONV) + t = TREE_OPERAND (t, 0); + if (TREE_CODE (t) == PTR_CONV) + t = TREE_OPERAND (t, 0); + t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE); + t = build_conv (REF_BIND, + build_reference_type (TREE_TYPE (TREE_TYPE (*ics))), + t); + ICS_STD_RANK (t) = ICS_STD_RANK (*ics); + *ics = t; + } +} + +/* If ICS is a REF_BIND, modify it appropriately, set TARGET_TYPE + to the type the reference originally referred to, and return 1. + Otherwise, return 0. */ + +static int +maybe_handle_ref_bind (ics, target_type) + tree* ics; + tree* target_type; +{ + if (TREE_CODE (*ics) == REF_BIND) + { + /* [over.ics.rank] + + When a parameter of reference type binds directly + (_dcl.init.ref_) to an argument expression, the implicit + conversion sequence is the identity conversion, unless the + argument expression has a type that is a derived class of the + parameter type, in which case the implicit conversion + sequence is a derived-to-base Conversion. + + If the parameter binds directly to the result of applying a + conversion function to the argument expression, the implicit + conversion sequence is a user-defined conversion sequence + (_over.ics.user_), with the second standard conversion + sequence either an identity conversion or, if the conversion + function returns an entity of a type that is a derived class + of the parameter type, a derived-to-base Conversion. + + When a parameter of reference type is not bound directly to + an argument expression, the conversion sequence is the one + required to convert the argument expression to the underlying + type of the reference according to _over.best.ics_. + Conceptually, this conversion sequence corresponds to + copy-initializing a temporary of the underlying type with the + argument expression. Any difference in top-level + cv-qualification is subsumed by the initialization itself and + does not constitute a conversion. */ + + tree old_ics = *ics; + + *target_type = TREE_TYPE (TREE_TYPE (*ics)); + *ics = TREE_OPERAND (*ics, 0); + if (TREE_CODE (*ics) == IDENTITY_CONV + && is_properly_derived_from (TREE_TYPE (*ics), *target_type)) + *ics = build_conv (BASE_CONV, *target_type, *ics); + ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics); + ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics); + + return 1; + } + + return 0; +} + +/* Compare two implicit conversion sequences according to the rules set out in + [over.ics.rank]. Return values: + + 1: ics1 is better than ics2 + -1: ics2 is better than ics1 + 0: ics1 and ics2 are indistinguishable */ + +static int +compare_ics (ics1, ics2) + tree ics1, ics2; +{ + tree from_type1; + tree from_type2; + tree to_type1; + tree to_type2; + tree deref_from_type1 = NULL_TREE; + tree deref_from_type2 = NULL_TREE; + tree deref_to_type1 = NULL_TREE; + tree deref_to_type2 = NULL_TREE; + + /* REF_BINDING is non-zero if the result of the conversion sequence + is a reference type. In that case TARGET_TYPE is the + type referred to by the reference. */ + int ref_binding1; + int ref_binding2; + tree target_type1; + tree target_type2; + + /* Handle implicit object parameters. */ + maybe_handle_implicit_object (&ics1); + maybe_handle_implicit_object (&ics2); + + /* Handle reference parameters. */ + ref_binding1 = maybe_handle_ref_bind (&ics1, &target_type1); + ref_binding2 = maybe_handle_ref_bind (&ics2, &target_type2); + + /* [over.ics.rank] + + When comparing the basic forms of implicit conversion sequences (as + defined in _over.best.ics_) + + --a standard conversion sequence (_over.ics.scs_) is a better + conversion sequence than a user-defined conversion sequence + or an ellipsis conversion sequence, and + + --a user-defined conversion sequence (_over.ics.user_) is a + better conversion sequence than an ellipsis conversion sequence + (_over.ics.ellipsis_). */ + if (ICS_RANK (ics1) > ICS_RANK (ics2)) + return -1; + else if (ICS_RANK (ics1) < ICS_RANK (ics2)) + return 1; + + if (ICS_RANK (ics1) == BAD_RANK) + { + /* Both ICS are bad. We try to make a decision based on what + would have happenned if they'd been good. */ + if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2) + || ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2)) + return -1; + else if (ICS_USER_FLAG (ics1) < ICS_USER_FLAG (ics2) + || ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2)) + return 1; + + /* We couldn't make up our minds; try to figure it out below. */ + } + + if (ICS_ELLIPSIS_FLAG (ics1)) + /* Both conversions are ellipsis conversions. */ + return 0; + + /* User-defined conversion sequence U1 is a better conversion sequence + than another user-defined conversion sequence U2 if they contain the + same user-defined conversion operator or constructor and if the sec- + ond standard conversion sequence of U1 is better than the second + standard conversion sequence of U2. */ + + if (ICS_USER_FLAG (ics1)) + { + tree t1, t2; + + for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0)) + if (TREE_CODE (t1) == AMBIG_CONV) + return 0; + for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0)) + if (TREE_CODE (t2) == AMBIG_CONV) + return 0; + + if (USER_CONV_FN (t1) != USER_CONV_FN (t2)) + return 0; + + /* We can just fall through here, after setting up + FROM_TYPE1 and FROM_TYPE2. */ + from_type1 = TREE_TYPE (t1); + from_type2 = TREE_TYPE (t2); + } + else + { + /* We're dealing with two standard conversion sequences. + + [over.ics.rank] + + Standard conversion sequence S1 is a better conversion + sequence than standard conversion sequence S2 if + + --S1 is a proper subsequence of S2 (comparing the conversion + sequences in the canonical form defined by _over.ics.scs_, + excluding any Lvalue Transformation; the identity + conversion sequence is considered to be a subsequence of + any non-identity conversion sequence */ + + from_type1 = ics1; + while (TREE_CODE (from_type1) != IDENTITY_CONV) + from_type1 = TREE_OPERAND (from_type1, 0); + from_type1 = TREE_TYPE (from_type1); + + from_type2 = ics2; + while (TREE_CODE (from_type2) != IDENTITY_CONV) + from_type2 = TREE_OPERAND (from_type2, 0); + from_type2 = TREE_TYPE (from_type2); + } + + if (same_type_p (from_type1, from_type2)) + { + if (is_subseq (ics1, ics2)) + return 1; + if (is_subseq (ics2, ics1)) + return -1; + } + /* Otherwise, one sequence cannot be a subsequence of the other; they + don't start with the same type. This can happen when comparing the + second standard conversion sequence in two user-defined conversion + sequences. */ + + /* [over.ics.rank] + + Or, if not that, + + --the rank of S1 is better than the rank of S2 (by the rules + defined below): + + Standard conversion sequences are ordered by their ranks: an Exact + Match is a better conversion than a Promotion, which is a better + conversion than a Conversion. + + Two conversion sequences with the same rank are indistinguishable + unless one of the following rules applies: + + --A conversion that is not a conversion of a pointer, or pointer + to member, to bool is better than another conversion that is such + a conversion. + + The ICS_STD_RANK automatically handles the pointer-to-bool rule, + so that we do not have to check it explicitly. */ + if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2)) + return 1; + else if (ICS_STD_RANK (ics2) < ICS_STD_RANK (ics1)) + return -1; + + to_type1 = TREE_TYPE (ics1); + to_type2 = TREE_TYPE (ics2); + + if (TYPE_PTR_P (from_type1) + && TYPE_PTR_P (from_type2) + && TYPE_PTR_P (to_type1) + && TYPE_PTR_P (to_type2)) + { + deref_from_type1 = TREE_TYPE (from_type1); + deref_from_type2 = TREE_TYPE (from_type2); + deref_to_type1 = TREE_TYPE (to_type1); + deref_to_type2 = TREE_TYPE (to_type2); + } + /* The rules for pointers to members A::* are just like the rules + for pointers A*, except opposite: if B is derived from A then + A::* converts to B::*, not vice versa. For that reason, we + switch the from_ and to_ variables here. */ + else if (TYPE_PTRMEM_P (from_type1) + && TYPE_PTRMEM_P (from_type2) + && TYPE_PTRMEM_P (to_type1) + && TYPE_PTRMEM_P (to_type2)) + { + deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1)); + deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2)); + deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1)); + deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2)); + } + else if (TYPE_PTRMEMFUNC_P (from_type1) + && TYPE_PTRMEMFUNC_P (from_type2) + && TYPE_PTRMEMFUNC_P (to_type1) + && TYPE_PTRMEMFUNC_P (to_type2)) + { + deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1); + deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2); + deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1); + deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2); + } + + if (deref_from_type1 != NULL_TREE + && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type1)) + && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type2))) + { + /* This was one of the pointer or pointer-like conversions. + + [over.ics.rank] + + --If class B is derived directly or indirectly from class A, + conversion of B* to A* is better than conversion of B* to + void*, and conversion of A* to void* is better than + conversion of B* to void*. */ + if (TREE_CODE (deref_to_type1) == VOID_TYPE + && TREE_CODE (deref_to_type2) == VOID_TYPE) + { + if (is_properly_derived_from (deref_from_type1, + deref_from_type2)) + return -1; + else if (is_properly_derived_from (deref_from_type2, + deref_from_type1)) + return 1; + } + else if (TREE_CODE (deref_to_type1) == VOID_TYPE + || TREE_CODE (deref_to_type2) == VOID_TYPE) + { + if (same_type_p (deref_from_type1, deref_from_type2)) + { + if (TREE_CODE (deref_to_type2) == VOID_TYPE) + { + if (is_properly_derived_from (deref_from_type1, + deref_to_type1)) + return 1; + } + /* We know that DEREF_TO_TYPE1 is `void' here. */ + else if (is_properly_derived_from (deref_from_type1, + deref_to_type2)) + return -1; + } + } + else if (IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type1)) + && IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type2))) + { + /* [over.ics.rank] + + --If class B is derived directly or indirectly from class A + and class C is derived directly or indirectly from B, + + --conversion of C* to B* is better than conversion of C* to + A*, + + --conversion of B* to A* is better than conversion of C* to + A* */ + if (same_type_p (deref_from_type1, deref_from_type2)) + { + if (is_properly_derived_from (deref_to_type1, + deref_to_type2)) + return 1; + else if (is_properly_derived_from (deref_to_type2, + deref_to_type1)) + return -1; + } + else if (same_type_p (deref_to_type1, deref_to_type2)) + { + if (is_properly_derived_from (deref_from_type2, + deref_from_type1)) + return 1; + else if (is_properly_derived_from (deref_from_type1, + deref_from_type2)) + return -1; + } + } + } + else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1)) + && same_type_p (from_type1, from_type2)) + { + /* [over.ics.rank] + + --binding of an expression of type C to a reference of type + B& is better than binding an expression of type C to a + reference of type A& + + --conversion of C to B is better than conversion of C to A, */ + if (is_properly_derived_from (from_type1, to_type1) + && is_properly_derived_from (from_type1, to_type2)) + { + if (is_properly_derived_from (to_type1, to_type2)) + return 1; + else if (is_properly_derived_from (to_type2, to_type1)) + return -1; + } + } + else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1)) + && same_type_p (to_type1, to_type2)) + { + /* [over.ics.rank] + + --binding of an expression of type B to a reference of type + A& is better than binding an expression of type C to a + reference of type A&, + + --onversion of B to A is better than conversion of C to A */ + if (is_properly_derived_from (from_type1, to_type1) + && is_properly_derived_from (from_type2, to_type1)) + { + if (is_properly_derived_from (from_type2, from_type1)) + return 1; + else if (is_properly_derived_from (from_type1, from_type2)) + return -1; + } + } + + /* [over.ics.rank] + + --S1 and S2 differ only in their qualification conversion and yield + similar types T1 and T2 (_conv.qual_), respectively, and the cv- + qualification signature of type T1 is a proper subset of the cv- + qualification signature of type T2 */ + if (TREE_CODE (ics1) == QUAL_CONV + && TREE_CODE (ics2) == QUAL_CONV + && same_type_p (from_type1, from_type2)) + return comp_cv_qual_signature (to_type1, to_type2); + + /* [over.ics.rank] + + --S1 and S2 are reference bindings (_dcl.init.ref_), and the + types to which the references refer are the same type except for + top-level cv-qualifiers, and the type to which the reference + initialized by S2 refers is more cv-qualified than the type to + which the reference initialized by S1 refers */ + + if (ref_binding1 && ref_binding2 + && same_type_p (TYPE_MAIN_VARIANT (to_type1), + TYPE_MAIN_VARIANT (to_type2))) + return comp_cv_qualification (target_type2, target_type1); + + /* Neither conversion sequence is better than the other. */ + return 0; +} + +/* The source type for this standard conversion sequence. */ + +static tree +source_type (t) + tree t; +{ + for (;; t = TREE_OPERAND (t, 0)) + { + if (TREE_CODE (t) == USER_CONV + || TREE_CODE (t) == AMBIG_CONV + || TREE_CODE (t) == IDENTITY_CONV) + return TREE_TYPE (t); + } + my_friendly_abort (1823); +} + +/* Note a warning about preferring WINNER to LOSER. We do this by storing + a pointer to LOSER and re-running joust to produce the warning if WINNER + is actually used. */ + +static void +add_warning (winner, loser) + struct z_candidate *winner, *loser; +{ + winner->warnings = expr_tree_cons (NULL_PTR, + build_expr_ptr_wrapper (loser), + winner->warnings); +} + +/* Compare two candidates for overloading as described in + [over.match.best]. Return values: + + 1: cand1 is better than cand2 + -1: cand2 is better than cand1 + 0: cand1 and cand2 are indistinguishable */ + +static int +joust (cand1, cand2, warn) + struct z_candidate *cand1, *cand2; + int warn; +{ + int winner = 0; + int i, off1 = 0, off2 = 0, len; + + /* Candidates that involve bad conversions are always worse than those + that don't. */ + if (cand1->viable > cand2->viable) + return 1; + if (cand1->viable < cand2->viable) + return -1; + + /* If we have two pseudo-candidates for conversions to the same type, + arbitrarily pick one. */ + if (TYPE_P (cand1->fn) && cand1->fn == cand2->fn) + return 1; + + /* a viable function F1 + is defined to be a better function than another viable function F2 if + for all arguments i, ICSi(F1) is not a worse conversion sequence than + ICSi(F2), and then */ + + /* for some argument j, ICSj(F1) is a better conversion sequence than + ICSj(F2) */ + + /* For comparing static and non-static member functions, we ignore the + implicit object parameter of the non-static function. The WP says to + pretend that the static function has an object parm, but that won't + work with operator overloading. */ + len = TREE_VEC_LENGTH (cand1->convs); + if (len != TREE_VEC_LENGTH (cand2->convs)) + { + if (DECL_STATIC_FUNCTION_P (cand1->fn) + && ! DECL_STATIC_FUNCTION_P (cand2->fn)) + off2 = 1; + else if (! DECL_STATIC_FUNCTION_P (cand1->fn) + && DECL_STATIC_FUNCTION_P (cand2->fn)) + { + off1 = 1; + --len; + } + else + my_friendly_abort (42); + } + + for (i = 0; i < len; ++i) + { + tree t1 = TREE_VEC_ELT (cand1->convs, i+off1); + tree t2 = TREE_VEC_ELT (cand2->convs, i+off2); + int comp = compare_ics (t1, t2); + + if (comp != 0) + { + if (warn_sign_promo + && ICS_RANK (t1) + ICS_RANK (t2) == STD_RANK + PROMO_RANK + && TREE_CODE (t1) == STD_CONV + && TREE_CODE (t2) == STD_CONV + && TREE_CODE (TREE_TYPE (t1)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (t2)) == INTEGER_TYPE + && (TYPE_PRECISION (TREE_TYPE (t1)) + == TYPE_PRECISION (TREE_TYPE (t2))) + && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (t1, 0))) + || (TREE_CODE (TREE_TYPE (TREE_OPERAND (t1, 0))) + == ENUMERAL_TYPE))) + { + tree type = TREE_TYPE (TREE_OPERAND (t1, 0)); + tree type1, type2; + struct z_candidate *w, *l; + if (comp > 0) + type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2), + w = cand1, l = cand2; + else + type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1), + w = cand2, l = cand1; + + if (warn) + { + cp_warning ("passing `%T' chooses `%T' over `%T'", + type, type1, type2); + cp_warning (" in call to `%D'", w->fn); + } + else + add_warning (w, l); + } + + if (winner && comp != winner) + { + winner = 0; + goto tweak; + } + winner = comp; + } + } + + /* warn about confusing overload resolution for user-defined conversions, + either between a constructor and a conversion op, or between two + conversion ops. */ + if (winner && cand1->second_conv + && ((DECL_CONSTRUCTOR_P (cand1->fn) + != DECL_CONSTRUCTOR_P (cand2->fn)) + /* Don't warn if the two conv ops convert to the same type... */ + || (! DECL_CONSTRUCTOR_P (cand1->fn) + && ! same_type_p (TREE_TYPE (TREE_TYPE (cand1->fn)), + TREE_TYPE (TREE_TYPE (cand2->fn)))))) + { + int comp = compare_ics (cand1->second_conv, cand2->second_conv); + if (comp != winner) + { + struct z_candidate *w, *l; + if (winner == 1) + w = cand1, l = cand2; + else + w = cand2, l = cand1; + if (warn) + { + tree source = source_type (TREE_VEC_ELT (w->convs, 0)); + if (! DECL_CONSTRUCTOR_P (w->fn)) + source = TREE_TYPE (source); + cp_warning ("choosing `%D' over `%D'", w->fn, l->fn); + cp_warning (" for conversion from `%T' to `%T'", + source, TREE_TYPE (w->second_conv)); + cp_warning (" because conversion sequence for the argument is better"); + } + else + add_warning (w, l); + } + } + + if (winner) + return winner; + + /* or, if not that, + F1 is a non-template function and F2 is a template function */ + + if (! cand1->template && cand2->template) + return 1; + else if (cand1->template && ! cand2->template) + return -1; + else if (cand1->template && cand2->template) + winner = more_specialized + (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template), + NULL_TREE); + + /* or, if not that, + the context is an initialization by user-defined conversion (see + _dcl.init_ and _over.match.user_) and the standard conversion + sequence from the return type of F1 to the destination type (i.e., + the type of the entity being initialized) is a better conversion + sequence than the standard conversion sequence from the return type + of F2 to the destination type. */ + + if (! winner && cand1->second_conv) + winner = compare_ics (cand1->second_conv, cand2->second_conv); + + /* If the built-in candidates are the same, arbitrarily pick one. */ + if (! winner && cand1->fn == cand2->fn + && TREE_CODE (cand1->fn) == IDENTIFIER_NODE) + { + for (i = 0; i < len; ++i) + if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)), + TREE_TYPE (TREE_VEC_ELT (cand2->convs, i)))) + break; + if (i == TREE_VEC_LENGTH (cand1->convs)) + return 1; + + /* Kludge around broken overloading rules whereby + Integer a, b; test ? a : b; is ambiguous, since there's a builtin + that takes references and another that takes values. */ + if (cand1->fn == ansi_opname[COND_EXPR]) + { + tree c1 = TREE_VEC_ELT (cand1->convs, 1); + tree c2 = TREE_VEC_ELT (cand2->convs, 1); + tree t1 = strip_top_quals (non_reference (TREE_TYPE (c1))); + tree t2 = strip_top_quals (non_reference (TREE_TYPE (c2))); + + if (same_type_p (t1, t2)) + { + if (TREE_CODE (c1) == REF_BIND && TREE_CODE (c2) != REF_BIND) + return 1; + if (TREE_CODE (c1) != REF_BIND && TREE_CODE (c2) == REF_BIND) + return -1; + } + } + } + +tweak: + + /* Extension: If the worst conversion for one candidate is worse than the + worst conversion for the other, take the first. */ + if (! winner && ! pedantic) + { + int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK; + + for (i = 0; i < len; ++i) + { + if (ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1)) > rank1) + rank1 = ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1)); + if (ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)) > rank2) + rank2 = ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)); + } + + if (rank1 < rank2) + return 1; + if (rank1 > rank2) + return -1; + } + + return winner; +} + +/* Given a list of candidates for overloading, find the best one, if any. + This algorithm has a worst case of O(2n) (winner is last), and a best + case of O(n/2) (totally ambiguous); much better than a sorting + algorithm. */ + +static struct z_candidate * +tourney (candidates) + struct z_candidate *candidates; +{ + struct z_candidate *champ = candidates, *challenger; + int fate; + int champ_compared_to_predecessor = 0; + + /* Walk through the list once, comparing each current champ to the next + candidate, knocking out a candidate or two with each comparison. */ + + for (challenger = champ->next; challenger; ) + { + fate = joust (champ, challenger, 0); + if (fate == 1) + challenger = challenger->next; + else + { + if (fate == 0) + { + champ = challenger->next; + if (champ == 0) + return 0; + champ_compared_to_predecessor = 0; + } + else + { + champ = challenger; + champ_compared_to_predecessor = 1; + } + + challenger = champ->next; + } + } + + /* Make sure the champ is better than all the candidates it hasn't yet + been compared to. */ + + for (challenger = candidates; + challenger != champ + && !(champ_compared_to_predecessor && challenger->next == champ); + challenger = challenger->next) + { + fate = joust (champ, challenger, 0); + if (fate != 1) + return 0; + } + + return champ; +} + +int +can_convert (to, from) + tree to, from; +{ + tree t = implicit_conversion (to, from, NULL_TREE, LOOKUP_NORMAL); + return (t && ! ICS_BAD_FLAG (t)); +} + +int +can_convert_arg (to, from, arg) + tree to, from, arg; +{ + tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL); + return (t && ! ICS_BAD_FLAG (t)); +} Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/call.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/class.c =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/class.c (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/class.c (revision 60969) @@ -0,0 +1,5753 @@ +/* Functions related to building classes and their related objects. + Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@cygnus.com) + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +/* High-level class interface. */ + +#include "config.h" +#include "system.h" +#include "tree.h" +#include "cp-tree.h" +#include "flags.h" +#include "rtl.h" +#include "output.h" +#include "toplev.h" +#include "splay-tree.h" + +#include "obstack.h" +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +/* This is how we tell when two virtual member functions are really the + same. */ +#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL)) + +extern void set_class_shadows PROTO ((tree)); + +/* The number of nested classes being processed. If we are not in the + scope of any class, this is zero. */ + +int current_class_depth; + +/* In order to deal with nested classes, we keep a stack of classes. + The topmost entry is the innermost class, and is the entry at index + CURRENT_CLASS_DEPTH */ + +typedef struct class_stack_node { + /* The name of the class. */ + tree name; + + /* The _TYPE node for the class. */ + tree type; + + /* The access specifier pending for new declarations in the scope of + this class. */ + tree access; + + /* If were defining TYPE, the names used in this class. */ + splay_tree names_used; +}* class_stack_node_t; + +/* The stack itself. This is an dynamically resized array. The + number of elements allocated is CURRENT_CLASS_STACK_SIZE. */ +static int current_class_stack_size; +static class_stack_node_t current_class_stack; + +/* When we're processing a member function, current_class_ptr is the + PARM_DECL for the `this' pointer. The current_class_ref is an + expression for `*this'. */ +tree current_class_ptr, current_class_ref; + +/* The following two can be derived from the previous one */ +tree current_class_name; /* IDENTIFIER_NODE: name of current class */ +tree current_class_type; /* _TYPE: the type of the current class */ +tree current_access_specifier; +tree previous_class_type; /* _TYPE: the previous type that was a class */ +tree previous_class_values; /* TREE_LIST: copy of the class_shadowed list + when leaving an outermost class scope. */ + +/* The obstack on which the cached class declarations are kept. */ +static struct obstack class_cache_obstack; +/* The first object allocated on that obstack. We can use + obstack_free with tis value to free the entire obstack. */ +char *class_cache_firstobj; + +struct base_info; + +static tree get_vfield_name PROTO((tree)); +static void finish_struct_anon PROTO((tree)); +static tree build_vbase_pointer PROTO((tree, tree)); +static tree build_vtable_entry PROTO((tree, tree)); +static tree get_vtable_name PROTO((tree)); +static tree get_derived_offset PROTO((tree, tree)); +static tree get_basefndecls PROTO((tree, tree)); +static void set_rtti_entry PROTO((tree, tree, tree)); +static tree build_vtable PROTO((tree, tree)); +static void prepare_fresh_vtable PROTO((tree, tree)); +static tree prepare_ctor_vtable PROTO((tree, tree, tree)); +static void fixup_vtable_deltas1 PROTO((tree, tree)); +static void fixup_vtable_deltas PROTO((tree, int, tree)); +static tree finish_one_ctor_vtable PROTO((tree, tree, tree, tree)); +static tree prepend_ctor_vfields_for_vbase PROTO((tree, tree, tree, tree, int, tree)); +static tree finish_ctor_vtables_for_vbases PROTO((tree, tree, tree)); +static tree finish_ctor_vtables_1 PROTO((tree, tree)); +static tree prepend_vbase_vfields PROTO((tree, int, tree)); +static void finish_ctor_vtables PROTO((tree)); +static void finish_vtbls PROTO((tree, int, tree)); +static void modify_vtable_entry PROTO((tree, tree, tree)); +static tree get_vtable_entry_n PROTO((tree, unsigned HOST_WIDE_INT)); +static void add_virtual_function PROTO((tree *, tree *, int *, tree, tree)); +static tree delete_duplicate_fields_1 PROTO((tree, tree)); +static void delete_duplicate_fields PROTO((tree)); +static void finish_struct_bits PROTO((tree, int)); +static int alter_access PROTO((tree, tree, tree, tree)); +static void handle_using_decl PROTO((tree, tree, tree, tree)); +static int overrides PROTO((tree, tree)); +static int strictly_overrides PROTO((tree, tree)); +static void merge_overrides PROTO((tree, tree, int, tree)); +static void override_one_vtable PROTO((tree, tree, tree)); +static void mark_overriders PROTO((tree, tree)); +static void check_for_override PROTO((tree, tree)); +static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree)); +static tree get_class_offset PROTO((tree, tree, tree, tree)); +static void modify_one_vtable PROTO((tree, tree, tree, tree)); +static void modify_all_vtables PROTO((tree, tree, tree)); +static void modify_all_direct_vtables PROTO((tree, int, tree, tree, + tree)); +static void modify_all_indirect_vtables PROTO((tree, int, int, tree, + tree, tree)); +static int finish_base_struct PROTO((tree, struct base_info *)); +static void finish_struct_methods PROTO((tree)); +static void maybe_warn_about_overly_private_class PROTO ((tree)); +static tree make_method_vec PROTO((int)); +static void free_method_vec PROTO((tree)); +static tree add_implicitly_declared_members PROTO((tree, int, int, int)); +static tree fixed_type_or_null PROTO((tree, int *)); +static tree resolve_address_of_overloaded_function PROTO((tree, tree, int, + int, tree)); +static void build_vtable_entry_ref PROTO((tree, tree, tree)); + +/* Way of stacking language names. */ +tree *current_lang_base, *current_lang_stack; +int current_lang_stacksize; + +/* Names of languages we recognize. */ +tree lang_name_c, lang_name_cplusplus, lang_name_java; +tree current_lang_name; + +/* When layout out an aggregate type, the size of the + basetypes (virtual and non-virtual) is passed to layout_record + via this node. */ +static tree base_layout_decl; + +/* Constants used for access control. */ +tree access_default_node; /* 0 */ +tree access_public_node; /* 1 */ +tree access_protected_node; /* 2 */ +tree access_private_node; /* 3 */ +tree access_default_virtual_node; /* 4 */ +tree access_public_virtual_node; /* 5 */ +tree access_protected_virtual_node; /* 6 */ +tree access_private_virtual_node; /* 7 */ + +/* Variables shared between class.c and call.c. */ + +#ifdef GATHER_STATISTICS +int n_vtables = 0; +int n_vtable_entries = 0; +int n_vtable_searches = 0; +int n_vtable_elems = 0; +int n_convert_harshness = 0; +int n_compute_conversion_costs = 0; +int n_build_method_call = 0; +int n_inner_fields_searched = 0; +#endif + +/* Virtual baseclass things. */ + +static tree +build_vbase_pointer (exp, type) + tree exp, type; +{ + char *name; + FORMAT_VBASE_NAME (name, type); + + return build_component_ref (exp, get_identifier (name), NULL_TREE, 0); +} + +#if 0 +/* Is the type of the EXPR, the complete type of the object? + If we are going to be wrong, we must be conservative, and return 0. */ + +static int +complete_type_p (expr) + tree expr; +{ + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (expr)); + while (1) + { + switch (TREE_CODE (expr)) + { + case SAVE_EXPR: + case INDIRECT_REF: + case ADDR_EXPR: + case NOP_EXPR: + case CONVERT_EXPR: + expr = TREE_OPERAND (expr, 0); + continue; + + case CALL_EXPR: + if (! TREE_HAS_CONSTRUCTOR (expr)) + break; + /* fall through... */ + case VAR_DECL: + case FIELD_DECL: + if (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE + && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (expr))) + && TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type) + return 1; + /* fall through... */ + case TARGET_EXPR: + case PARM_DECL: + if (IS_AGGR_TYPE (TREE_TYPE (expr)) + && TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type) + return 1; + /* fall through... */ + case PLUS_EXPR: + default: + break; + } + break; + } + return 0; +} +#endif + +/* Build multi-level access to EXPR using hierarchy path PATH. + CODE is PLUS_EXPR if we are going with the grain, + and MINUS_EXPR if we are not (in which case, we cannot traverse + virtual baseclass links). + + TYPE is the type we want this path to have on exit. + + NONNULL is non-zero if we know (for any reason) that EXPR is + not, in fact, zero. */ + +tree +build_vbase_path (code, type, expr, path, nonnull) + enum tree_code code; + tree type, expr, path; + int nonnull; +{ + register int changed = 0; + tree last = NULL_TREE, last_virtual = NULL_TREE; + int fixed_type_p; + tree null_expr = 0, nonnull_expr; + tree basetype; + tree offset = integer_zero_node; + + if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE) + return build1 (NOP_EXPR, type, expr); + + /* If -fthis-is-variable, we might have set nonnull incorrectly. We + don't care enough to get this right, so just clear it. */ + if (flag_this_is_variable > 0) + nonnull = 0; + + /* We could do better if we had additional logic to convert back to the + unconverted type (the static type of the complete object), and then + convert back to the type we want. Until that is done, we only optimize + if the complete type is the same type as expr has. */ + fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull); + + if (!fixed_type_p && TREE_SIDE_EFFECTS (expr)) + expr = save_expr (expr); + nonnull_expr = expr; + + if (BINFO_INHERITANCE_CHAIN (path)) + path = reverse_path (path); + + basetype = BINFO_TYPE (path); + + while (path) + { + if (TREE_VIA_VIRTUAL (path)) + { + last_virtual = BINFO_TYPE (path); + if (code == PLUS_EXPR) + { + changed = ! fixed_type_p; + + if (changed) + { + tree ind; + + /* We already check for ambiguous things in the caller, just + find a path. */ + if (last) + { + tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (nonnull_expr))), 0); + nonnull_expr = convert_pointer_to_real (binfo, nonnull_expr); + } + ind = build_indirect_ref (nonnull_expr, NULL_PTR); + nonnull_expr = build_vbase_pointer (ind, last_virtual); + if (nonnull == 0 + && TREE_CODE (type) == POINTER_TYPE + && null_expr == NULL_TREE) + { + null_expr = build1 (NOP_EXPR, build_pointer_type (last_virtual), integer_zero_node); + expr = build (COND_EXPR, build_pointer_type (last_virtual), + build (EQ_EXPR, boolean_type_node, expr, + integer_zero_node), + null_expr, nonnull_expr); + } + } + /* else we'll figure out the offset below. */ + + /* Happens in the case of parse errors. */ + if (nonnull_expr == error_mark_node) + return error_mark_node; + } + else + { + cp_error ("cannot cast up from virtual baseclass `%T'", + last_virtual); + return error_mark_node; + } + } + last = path; + path = BINFO_INHERITANCE_CHAIN (path); + } + /* LAST is now the last basetype assoc on the path. */ + + /* A pointer to a virtual base member of a non-null object + is non-null. Therefore, we only need to test for zeroness once. + Make EXPR the canonical expression to deal with here. */ + if (null_expr) + { + TREE_OPERAND (expr, 2) = nonnull_expr; + TREE_TYPE (expr) = TREE_TYPE (TREE_OPERAND (expr, 1)) + = TREE_TYPE (nonnull_expr); + } + else + expr = nonnull_expr; + + /* If we go through any virtual base pointers, make sure that + casts to BASETYPE from the last virtual base class use + the right value for BASETYPE. */ + if (changed) + { + tree intype = TREE_TYPE (TREE_TYPE (expr)); + if (TYPE_MAIN_VARIANT (intype) != BINFO_TYPE (last)) + { + tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (intype), 0); + offset = BINFO_OFFSET (binfo); + } + } + else + { + if (last_virtual) + { + offset = BINFO_OFFSET (binfo_member (last_virtual, + CLASSTYPE_VBASECLASSES (basetype))); + offset = size_binop (PLUS_EXPR, offset, BINFO_OFFSET (last)); + } + else + offset = BINFO_OFFSET (last); + } + + if (TREE_INT_CST_LOW (offset)) + { + /* Bash types to make the backend happy. */ + offset = cp_convert (type, offset); +#if 0 + /* This shouldn't be necessary. (mrs) */ + expr = build1 (NOP_EXPR, type, expr); +#endif + + /* If expr might be 0, we need to preserve that zeroness. */ + if (nonnull == 0) + { + if (null_expr) + TREE_TYPE (null_expr) = type; + else + null_expr = build1 (NOP_EXPR, type, integer_zero_node); + if (TREE_SIDE_EFFECTS (expr)) + expr = save_expr (expr); + + return build (COND_EXPR, type, + build (EQ_EXPR, boolean_type_node, expr, integer_zero_node), + null_expr, + build (code, type, expr, offset)); + } + else return build (code, type, expr, offset); + } + + /* Cannot change the TREE_TYPE of a NOP_EXPR here, since it may + be used multiple times in initialization of multiple inheritance. */ + if (null_expr) + { + TREE_TYPE (expr) = type; + return expr; + } + else + return build1 (NOP_EXPR, type, expr); +} + +/* Virtual function things. */ + +/* Build an entry in the virtual function table. + DELTA is the offset for the `this' pointer. + PFN is an ADDR_EXPR containing a pointer to the virtual function. + Note that the index (DELTA2) in the virtual function table + is always 0. */ + +static tree +build_vtable_entry (delta, pfn) + tree delta, pfn; +{ + if (flag_vtable_thunks) + { + HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta); + if (idelta && ! DECL_ABSTRACT_VIRTUAL_P (TREE_OPERAND (pfn, 0))) + { + pfn = build1 (ADDR_EXPR, vtable_entry_type, + make_thunk (pfn, idelta)); + TREE_READONLY (pfn) = 1; + TREE_CONSTANT (pfn) = 1; + } +#ifdef GATHER_STATISTICS + n_vtable_entries += 1; +#endif + return pfn; + } + else + { + extern int flag_huge_objects; + tree elems = expr_tree_cons (NULL_TREE, delta, + expr_tree_cons (NULL_TREE, integer_zero_node, + build_expr_list (NULL_TREE, pfn))); + tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems); + + /* DELTA used to be constructed by `size_int' and/or size_binop, + which caused overflow problems when it was negative. That should + be fixed now. */ + + if (! int_fits_type_p (delta, delta_type_node)) + { + if (flag_huge_objects) + sorry ("object size exceeds built-in limit for virtual function table implementation"); + else + sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects"); + } + + TREE_CONSTANT (entry) = 1; + TREE_STATIC (entry) = 1; + TREE_READONLY (entry) = 1; + +#ifdef GATHER_STATISTICS + n_vtable_entries += 1; +#endif + + return entry; + } +} + +/* We want to give the assembler the vtable identifier as well as + the offset to the function pointer. So we generate + + __asm__ __volatile__ (".vtable_entry %c0, %c1" + : : "s"(&class_vtable), + "i"((long)&vtbl[idx].pfn - (long)&vtbl[0])); */ + +static void +build_vtable_entry_ref (basetype, vtbl, idx) + tree basetype, vtbl, idx; +{ + static char asm_stmt[] = ".vtable_entry %c0, %c1"; + tree s, i, i2; + + s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0); + s = build_tree_list (build_string (1, "s"), s); + + i = build_array_ref (vtbl, idx); + if (!flag_vtable_thunks) + i = build_component_ref (i, pfn_identifier, vtable_entry_type, 0); + i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0)); + i2 = build_array_ref (vtbl, build_int_2(0,0)); + i2 = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i2, 0)); + i = build_binary_op (MINUS_EXPR, i, i2); + i = build_tree_list (build_string (1, "i"), i); + + expand_asm_operands (build_string (sizeof(asm_stmt)-1, asm_stmt), + NULL_TREE, chainon (s, i), NULL_TREE, 1, NULL, 0); +} + +/* Given an object INSTANCE, return an expression which yields the + virtual function vtable element corresponding to INDEX. There are + many special cases for INSTANCE which we take care of here, mainly + to avoid creating extra tree nodes when we don't have to. */ + +tree +build_vtbl_ref (instance, idx) + tree instance, idx; +{ + tree vtbl, aref; + tree basetype = TREE_TYPE (instance); + + if (TREE_CODE (basetype) == REFERENCE_TYPE) + basetype = TREE_TYPE (basetype); + + if (instance == current_class_ref) + vtbl = build_vfield_ref (instance, basetype); + else + { + if (optimize) + { + /* Try to figure out what a reference refers to, and + access its virtual function table directly. */ + tree ref = NULL_TREE; + + if (TREE_CODE (instance) == INDIRECT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (instance, 0))) == REFERENCE_TYPE) + ref = TREE_OPERAND (instance, 0); + else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) + ref = instance; + + if (ref && TREE_CODE (ref) == VAR_DECL + && DECL_INITIAL (ref)) + { + tree init = DECL_INITIAL (ref); + + while (TREE_CODE (init) == NOP_EXPR + || TREE_CODE (init) == NON_LVALUE_EXPR) + init = TREE_OPERAND (init, 0); + if (TREE_CODE (init) == ADDR_EXPR) + { + init = TREE_OPERAND (init, 0); + if (IS_AGGR_TYPE (TREE_TYPE (init)) + && (TREE_CODE (init) == PARM_DECL + || TREE_CODE (init) == VAR_DECL)) + instance = init; + } + } + } + + if (IS_AGGR_TYPE (TREE_TYPE (instance)) + && (TREE_CODE (instance) == RESULT_DECL + || TREE_CODE (instance) == PARM_DECL + || TREE_CODE (instance) == VAR_DECL)) + vtbl = TYPE_BINFO_VTABLE (basetype); + else + vtbl = build_vfield_ref (instance, basetype); + } + + assemble_external (vtbl); + + if (flag_vtable_gc) + build_vtable_entry_ref (basetype, vtbl, idx); + + aref = build_array_ref (vtbl, idx); + + return aref; +} + +/* Given an object INSTANCE, return an expression which yields the + virtual function corresponding to INDEX. There are many special + cases for INSTANCE which we take care of here, mainly to avoid + creating extra tree nodes when we don't have to. */ + +tree +build_vfn_ref (ptr_to_instptr, instance, idx) + tree *ptr_to_instptr, instance; + tree idx; +{ + tree aref = build_vtbl_ref (instance, idx); + + /* When using thunks, there is no extra delta, and we get the pfn + directly. */ + if (flag_vtable_thunks) + return aref; + + if (ptr_to_instptr) + { + /* Save the intermediate result in a SAVE_EXPR so we don't have to + compute each component of the virtual function pointer twice. */ + if (TREE_CODE (aref) == INDIRECT_REF) + TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0)); + + *ptr_to_instptr + = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr), + *ptr_to_instptr, + cp_convert (ptrdiff_type_node, + build_component_ref (aref, delta_identifier, NULL_TREE, 0))); + } + + return build_component_ref (aref, pfn_identifier, NULL_TREE, 0); +} + +/* Return the name of the virtual function table (as an IDENTIFIER_NODE) + for the given TYPE. */ + +static tree +get_vtable_name (type) + tree type; +{ + tree type_id = build_typename_overload (type); + char *buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + + IDENTIFIER_LENGTH (type_id) + 2); + const char *ptr = IDENTIFIER_POINTER (type_id); + int i; + for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ; +#if 0 + /* We don't take off the numbers; prepare_fresh_vtable uses the + DECL_ASSEMBLER_NAME for the type, which includes the number + in `3foo'. If we were to pull them off here, we'd end up with + something like `_vt.foo.3bar', instead of a uniform definition. */ + while (ptr[i] >= '0' && ptr[i] <= '9') + i += 1; +#endif + sprintf (buf, VTABLE_NAME_FORMAT, ptr+i); + return get_identifier (buf); +} + +/* Return the offset to the main vtable for a given base BINFO. */ + +tree +get_vfield_offset (binfo) + tree binfo; +{ + tree tmp + = size_binop (FLOOR_DIV_EXPR, + DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))), + size_int (BITS_PER_UNIT)); + tmp = convert (sizetype, tmp); + return size_binop (PLUS_EXPR, tmp, BINFO_OFFSET (binfo)); +} + +/* Get the offset to the start of the original binfo that we derived + this binfo from. If we find TYPE first, return the offset only + that far. The shortened search is useful because the this pointer + on method calling is expected to point to a DECL_CONTEXT (fndecl) + object, and not a baseclass of it. */ + +static tree +get_derived_offset (binfo, type) + tree binfo, type; +{ + tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); + tree offset2; + int i; + while (BINFO_BASETYPES (binfo) + && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) + { + tree binfos = BINFO_BASETYPES (binfo); + if (BINFO_TYPE (binfo) == type) + break; + binfo = TREE_VEC_ELT (binfos, i); + } + offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); + return size_binop (MINUS_EXPR, offset1, offset2); +} + +/* Update the rtti info for this class. */ + +static void +set_rtti_entry (virtuals, offset, type) + tree virtuals, offset, type; +{ + tree vfn; + + if (CLASSTYPE_COM_INTERFACE (type)) + return; + + if (flag_rtti) + vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn_unused (type)); + else + vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node); + TREE_CONSTANT (vfn) = 1; + + if (! flag_vtable_thunks) + TREE_VALUE (virtuals) = build_vtable_entry (offset, vfn); + else + { + tree voff = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); + TREE_CONSTANT (voff) = 1; + + TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff); + + /* The second slot is for the tdesc pointer when thunks are used. */ + TREE_VALUE (TREE_CHAIN (virtuals)) + = build_vtable_entry (integer_zero_node, vfn); + } +} + +/* Build a virtual function for type TYPE. + If BINFO is non-NULL, build the vtable starting with the initial + approximation that it is the same as the one which is the head of + the association list. */ + +static tree +build_vtable (binfo, type) + tree binfo, type; +{ + tree name = get_vtable_name (type); + tree virtuals, decl; + + if (binfo) + { + tree offset; + + virtuals = copy_list (BINFO_VIRTUALS (binfo)); + decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo))); + + /* Now do rtti stuff. */ + offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE); + offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset); + set_rtti_entry (virtuals, offset, type); + } + else + { + virtuals = NULL_TREE; + decl = build_lang_decl (VAR_DECL, name, void_type_node); + } + +#ifdef GATHER_STATISTICS + n_vtables += 1; + n_vtable_elems += list_length (virtuals); +#endif + + /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ + import_export_vtable (decl, type, 0); + + decl = pushdecl_top_level (decl); + SET_IDENTIFIER_GLOBAL_VALUE (name, decl); + /* Initialize the association list for this type, based + on our first approximation. */ + TYPE_BINFO_VTABLE (type) = decl; + TYPE_BINFO_VIRTUALS (type) = virtuals; + + DECL_ARTIFICIAL (decl) = 1; + TREE_STATIC (decl) = 1; +#ifndef WRITABLE_VTABLES + /* Make them READONLY by default. (mrs) */ + TREE_READONLY (decl) = 1; +#endif + /* At one time the vtable info was grabbed 2 words at a time. This + fails on sparc unless you have 8-byte alignment. (tiemann) */ + DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node), + DECL_ALIGN (decl)); + + DECL_VIRTUAL_P (decl) = 1; + DECL_CONTEXT (decl) = type; + + binfo = TYPE_BINFO (type); + SET_BINFO_NEW_VTABLE_MARKED (binfo); + return decl; +} + +extern tree signed_size_zero_node; + +/* Give TYPE a new virtual function table which is initialized + with a skeleton-copy of its original initialization. The only + entry that changes is the `delta' entry, so we can really + share a lot of structure. + + FOR_TYPE is the derived type which caused this table to + be needed. + + BINFO is the type association which provided TYPE for FOR_TYPE. + + The order in which vtables are built (by calling this function) for + an object must remain the same, otherwise a binary incompatibility + can result. */ + +static void +prepare_fresh_vtable (binfo, for_type) + tree binfo, for_type; +{ + tree basetype; + tree orig_decl = BINFO_VTABLE (binfo); + tree name; + tree new_decl; + tree offset; + tree path = binfo; + char *buf, *buf2; + char joiner = '_'; + int i; + +#ifdef JOINER + joiner = JOINER; +#endif + + basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo)); + + buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype); + i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1; + + /* We know that the vtable that we are going to create doesn't exist + yet in the global namespace, and when we finish, it will be + pushed into the global namespace. In complex MI hierarchies, we + have to loop while the name we are thinking of adding is globally + defined, adding more name components to the vtable name as we + loop, until the name is unique. This is because in complex MI + cases, we might have the same base more than once. This means + that the order in which this function is called for vtables must + remain the same, otherwise binary compatibility can be + compromised. */ + + while (1) + { + char *buf1 = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (for_type) + + 1 + i); + char *new_buf2; + + sprintf (buf1, "%s%c%s", TYPE_ASSEMBLER_NAME_STRING (for_type), joiner, + buf2); + buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + strlen (buf1) + 1); + sprintf (buf, VTABLE_NAME_FORMAT, buf1); + name = get_identifier (buf); + + /* If this name doesn't clash, then we can use it, otherwise + we add more to the name until it is unique. */ + + if (! IDENTIFIER_GLOBAL_VALUE (name)) + break; + + /* Set values for next loop through, if the name isn't unique. */ + + path = BINFO_INHERITANCE_CHAIN (path); + + /* We better not run out of stuff to make it unique. */ + my_friendly_assert (path != NULL_TREE, 368); + + basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (path)); + + if (for_type == basetype) + { + /* If we run out of basetypes in the path, we have already + found created a vtable with that name before, we now + resort to tacking on _%d to distinguish them. */ + int j = 2; + i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i + 1 + 3; + buf1 = (char *) alloca (i); + do { + sprintf (buf1, "%s%c%s%c%d", + TYPE_ASSEMBLER_NAME_STRING (basetype), joiner, + buf2, joiner, j); + buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + + strlen (buf1) + 1); + sprintf (buf, VTABLE_NAME_FORMAT, buf1); + name = get_identifier (buf); + + /* If this name doesn't clash, then we can use it, + otherwise we add something different to the name until + it is unique. */ + } while (++j <= 999 && IDENTIFIER_GLOBAL_VALUE (name)); + + /* Hey, they really like MI don't they? Increase the 3 + above to 6, and the 999 to 999999. :-) */ + my_friendly_assert (j <= 999, 369); + + break; + } + + i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i; + new_buf2 = (char *) alloca (i); + sprintf (new_buf2, "%s%c%s", + TYPE_ASSEMBLER_NAME_STRING (basetype), joiner, buf2); + buf2 = new_buf2; + } + + new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); + /* Remember which class this vtable is really for. */ + DECL_CONTEXT (new_decl) = for_type; + + DECL_ARTIFICIAL (new_decl) = 1; + TREE_STATIC (new_decl) = 1; + BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl); + DECL_VIRTUAL_P (new_decl) = 1; +#ifndef WRITABLE_VTABLES + /* Make them READONLY by default. (mrs) */ + TREE_READONLY (new_decl) = 1; +#endif + DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl); + + /* Make fresh virtual list, so we can smash it later. */ + BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo)); + + if (TREE_VIA_VIRTUAL (binfo)) + { + tree binfo1 = binfo_member (BINFO_TYPE (binfo), + CLASSTYPE_VBASECLASSES (for_type)); + + /* XXX - This should never happen, if it does, the caller should + ensure that the binfo is from for_type's binfos, not from any + base type's. We can remove all this code after a while. */ + if (binfo1 != binfo) + warning ("internal inconsistency: binfo offset error for rtti"); + + offset = BINFO_OFFSET (binfo1); + } + else + offset = BINFO_OFFSET (binfo); + + set_rtti_entry (BINFO_VIRTUALS (binfo), + ssize_binop (MINUS_EXPR, integer_zero_node, offset), + for_type); + +#ifdef GATHER_STATISTICS + n_vtables += 1; + n_vtable_elems += list_length (BINFO_VIRTUALS (binfo)); +#endif + + /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ + import_export_vtable (new_decl, for_type, 0); + + if (TREE_VIA_VIRTUAL (binfo)) + my_friendly_assert (binfo == binfo_member (BINFO_TYPE (binfo), + CLASSTYPE_VBASECLASSES (current_class_type)), + 170); + SET_BINFO_NEW_VTABLE_MARKED (binfo); +} + +/* Return a new vtable for use in initialization of the BASE subobject + of COMPLETE_TYPE. The vtable there goes into the vfield of the + VBASEBASE virtual subobject. */ + +static tree +prepare_ctor_vtable (complete_type, base, vbasebase) + tree complete_type, base, vbasebase; +{ + tree orig_decl = BINFO_VTABLE (vbasebase); + tree name = get_vlist_vtable_id (base, vbasebase); + tree new_decl; + + new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); + /* Remember which class this vtable is really for. */ + DECL_CONTEXT (new_decl) = complete_type; + + DECL_ARTIFICIAL (new_decl) = 1; + TREE_STATIC (new_decl) = 1; + new_decl = pushdecl_top_level (new_decl); + DECL_VIRTUAL_P (new_decl) = 1; +#ifndef WRITABLE_VTABLES + /* Make them READONLY by default. (mrs) */ + TREE_READONLY (new_decl) = 1; +#endif + DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl); + +#ifdef GATHER_STATISTICS + n_vtables += 1; + n_vtable_elems += list_length (BINFO_VIRTUALS (binfo)); +#endif + + /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ + import_export_vtable (new_decl, complete_type, 0); + + return new_decl; +} + +#if 0 +/* Access the virtual function table entry that logically + contains BASE_FNDECL. VIRTUALS is the virtual function table's + initializer. We can run off the end, when dealing with virtual + destructors in MI situations, return NULL_TREE in that case. */ + +static tree +get_vtable_entry (virtuals, base_fndecl) + tree virtuals, base_fndecl; +{ + unsigned HOST_WIDE_INT n = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD + ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)) + & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1)) + : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))); + +#ifdef GATHER_STATISTICS + n_vtable_searches += n; +#endif + + while (n > 0 && virtuals) + { + --n; + virtuals = TREE_CHAIN (virtuals); + } + return virtuals; +} +#endif + +/* Put new entry ENTRY into virtual function table initializer + VIRTUALS. + + Also update DECL_VINDEX (FNDECL). */ + +static void +modify_vtable_entry (old_entry_in_list, new_entry, fndecl) + tree old_entry_in_list, new_entry, fndecl; +{ + tree base_fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list)), 0); + +#ifdef NOTQUITE + cp_warning ("replaced %D with %D", DECL_ASSEMBLER_NAME (base_fndecl), + DECL_ASSEMBLER_NAME (fndecl)); +#endif + TREE_VALUE (old_entry_in_list) = new_entry; + + /* Now assign virtual dispatch information, if unset. */ + /* We can dispatch this, through any overridden base function. */ + if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) + { + DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl); + DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl); + } +} + +/* Access the virtual function table entry N. VIRTUALS is the virtual + function table's initializer. */ + +static tree +get_vtable_entry_n (virtuals, n) + tree virtuals; + unsigned HOST_WIDE_INT n; +{ + while (n > 0) + { + --n; + virtuals = TREE_CHAIN (virtuals); + } + return virtuals; +} + +/* Add a virtual function to all the appropriate vtables for the class + T. DECL_VINDEX(X) should be error_mark_node, if we want to + allocate a new slot in our table. If it is error_mark_node, we + know that no other function from another vtable is overridden by X. + HAS_VIRTUAL keeps track of how many virtuals there are in our main + vtable for the type, and we build upon the PENDING_VIRTUALS list + and return it. */ + +static void +add_virtual_function (pv, phv, has_virtual, fndecl, t) + tree *pv, *phv; + int *has_virtual; + tree fndecl; + tree t; /* Structure type. */ +{ + tree pending_virtuals = *pv; + tree pending_hard_virtuals = *phv; + + /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely + convert to void *. Make such a conversion here. */ + tree vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl); + TREE_CONSTANT (vfn) = 1; + +#ifndef DUMB_USER + if (current_class_type == 0) + cp_warning ("internal problem, current_class_type is zero when adding `%D', please report", + fndecl); + if (current_class_type && t != current_class_type) + cp_warning ("internal problem, current_class_type differs when adding `%D', please report", + fndecl); +#endif + + /* If the virtual function is a redefinition of a prior one, + figure out in which base class the new definition goes, + and if necessary, make a fresh virtual function table + to hold that entry. */ + if (DECL_VINDEX (fndecl) == error_mark_node) + { + tree entry; + + /* We remember that this was the base sub-object for rtti. */ + CLASSTYPE_RTTI (t) = t; + + /* If we are using thunks, use two slots at the front, one + for the offset pointer, one for the tdesc pointer. + For ARM-style vtables, use the same slot for both. */ + if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t)) + { + if (flag_vtable_thunks) + *has_virtual = 2; + else + *has_virtual = 1; + } + + /* Build a new INT_CST for this DECL_VINDEX. */ + { + static tree index_table[256]; + tree idx; + /* We skip a slot for the offset/tdesc entry. */ + int i = (*has_virtual)++; + + if (i >= 256 || index_table[i] == 0) + { + idx = build_int_2 (i, 0); + if (i < 256) + index_table[i] = idx; + } + else + idx = index_table[i]; + + /* Now assign virtual dispatch information. */ + DECL_VINDEX (fndecl) = idx; + DECL_CONTEXT (fndecl) = t; + } + entry = build_vtable_entry (integer_zero_node, vfn); + pending_virtuals = tree_cons (DECL_VINDEX (fndecl), entry, pending_virtuals); + } + /* Might already be INTEGER_CST if declared twice in class. We will + give error later or we've already given it. */ + else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) + { + /* Need an entry in some other virtual function table. + Deal with this after we have laid out our virtual base classes. */ + pending_hard_virtuals = temp_tree_cons (fndecl, vfn, pending_hard_virtuals); + } + *pv = pending_virtuals; + *phv = pending_hard_virtuals; +} + +/* Obstack on which to build the vector of class methods. */ +struct obstack class_obstack; +extern struct obstack *current_obstack; + +/* These are method vectors that were too small for the number of + methods in some class, and so were abandoned. */ +static tree free_method_vecs; + +/* Returns a method vector with enough room for N methods. N should + be a power of two. */ + +static tree +make_method_vec (n) + int n; +{ + tree new_vec; + tree* t; + + for (t = &free_method_vecs; *t; t = &(TREE_CHAIN (*t))) + /* Note that we don't use >= n here because we don't want to + allocate a very large vector where it isn't needed. */ + if (TREE_VEC_LENGTH (*t) == n) + { + new_vec = *t; + *t = TREE_CHAIN (new_vec); + TREE_CHAIN (new_vec) = NULL_TREE; + bzero ((PTR) &TREE_VEC_ELT (new_vec, 0), n * sizeof (tree)); + return new_vec; + } + + new_vec = make_tree_vec (n); + return new_vec; +} + +/* Free the method vector VEC. */ + +static void +free_method_vec (vec) + tree vec; +{ + TREE_CHAIN (vec) = free_method_vecs; + free_method_vecs = vec; +} + +/* Add method METHOD to class TYPE. + + 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) + tree type, *fields, method; +{ + push_obstacks_nochange (); + end_temporary_allocation (); + + /* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably + redundant. */ + DECL_CONTEXT (method) = type; + DECL_CLASS_CONTEXT (method) = type; + + if (fields && *fields) + *fields = build_overload (method, *fields); + else + { + int len; + int slot; + tree method_vec; + + if (!CLASSTYPE_METHOD_VEC (type)) + /* Make a new method vector. We start with 8 entries. We must + allocate at least two (for constructors and destructors), and + we're going to end up with an assignment operator at some + point as well. + + We could use a TREE_LIST for now, and convert it to a + TREE_VEC in finish_struct, but we would probably waste more + memory making the links in the list than we would by + over-allocating the size of the vector here. Furthermore, + we would complicate all the code that expects this to be a + vector. We keep a free list of vectors that we outgrew so + that we don't really waste any memory. */ + CLASSTYPE_METHOD_VEC (type) = make_method_vec (8); + + method_vec = CLASSTYPE_METHOD_VEC (type); + len = TREE_VEC_LENGTH (method_vec); + + if (DECL_NAME (method) == constructor_name (type)) + /* A new constructor or destructor. Constructors go in + slot 0; destructors go in slot 1. */ + slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0; + else + { + /* See if we already have an entry with this name. */ + for (slot = 2; slot < len; ++slot) + if (!TREE_VEC_ELT (method_vec, slot) + || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, + slot))) + == DECL_NAME (method))) + break; + + if (slot == len) + { + /* We need a bigger method vector. */ + tree new_vec = make_method_vec (2 * len); + bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0), + (PTR) &TREE_VEC_ELT (new_vec, 0), + len * sizeof (tree)); + free_method_vec (method_vec); + len = 2 * len; + method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec; + } + + if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot)) + { + /* Type conversion operators have to come before + ordinary methods; add_conversions depends on this to + speed up looking for conversion operators. So, if + necessary, we slide some of the vector elements up. + In theory, this makes this algorithm O(N^2) but we + don't expect many conversion operators. */ + for (slot = 2; slot < len; ++slot) + { + tree fn = TREE_VEC_ELT (method_vec, slot); + + if (!fn) + /* There are no more entries in the vector, so we + can insert the new conversion operator here. */ + break; + + if (!DECL_CONV_FN_P (OVL_CURRENT (fn))) + /* We can insert the new function right at the + SLOTth position. */ + break; + } + + if (!TREE_VEC_ELT (method_vec, slot)) + /* There is nothing in the Ith slot, so we can avoid + moving anything. */ + ; + else + { + /* We know the last slot in the vector is empty + because we know that at this point there's room + for a new function. */ + bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot), + (PTR) &TREE_VEC_ELT (method_vec, slot + 1), + (len - slot - 1) * sizeof (tree)); + TREE_VEC_ELT (method_vec, slot) = NULL_TREE; + } + } + } + + 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, slot); + fns; + fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + + if (TREE_CODE (fn) != TREE_CODE (method)) + continue; + + if (TREE_CODE (method) != TEMPLATE_DECL) + { + /* [over.load] Member function declarations with the + same name and the same parameter types cannot be + overloaded if any of them is a static member + function declaration. */ + if (DECL_STATIC_FUNCTION_P (fn) + != DECL_STATIC_FUNCTION_P (method)) + { + tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn)); + tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method)); + + if (! DECL_STATIC_FUNCTION_P (fn)) + parms1 = TREE_CHAIN (parms1); + else + parms2 = TREE_CHAIN (parms2); + + if (compparms (parms1, parms2)) + cp_error ("`%#D' and `%#D' cannot be overloaded", + fn, method); + } + + /* 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 merge the + declarations because that will confuse things if the + methods have inline definitions. In particular, we + will crash while processing the definitions. */ + return; + } + } + + /* Actually insert the new method. */ + TREE_VEC_ELT (method_vec, slot) + = build_overload (method, TREE_VEC_ELT (method_vec, slot)); + + /* Add the new binding. */ + if (!DECL_CONSTRUCTOR_P (method) + && !DECL_DESTRUCTOR_P (method)) + push_class_level_binding (DECL_NAME (method), + TREE_VEC_ELT (method_vec, slot)); + } + pop_obstacks (); +} + +/* Subroutines of finish_struct. */ + +/* Look through the list of fields for this struct, deleting + duplicates as we go. This must be recursive to handle + anonymous unions. + + FIELD is the field which may not appear anywhere in FIELDS. + FIELD_PTR, if non-null, is the starting point at which + chained deletions may take place. + The value returned is the first acceptable entry found + in FIELDS. + + Note that anonymous fields which are not of UNION_TYPE are + not duplicates, they are just anonymous fields. This happens + when we have unnamed bitfields, for example. */ + +static tree +delete_duplicate_fields_1 (field, fields) + tree field, fields; +{ + tree x; + tree prev = 0; + if (DECL_NAME (field) == 0) + { + if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE) + return fields; + + for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x)) + fields = delete_duplicate_fields_1 (x, fields); + return fields; + } + else + { + for (x = fields; x; prev = x, x = TREE_CHAIN (x)) + { + if (DECL_NAME (x) == 0) + { + if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE) + continue; + TYPE_FIELDS (TREE_TYPE (x)) + = delete_duplicate_fields_1 (field, TYPE_FIELDS (TREE_TYPE (x))); + if (TYPE_FIELDS (TREE_TYPE (x)) == 0) + { + if (prev == 0) + fields = TREE_CHAIN (fields); + else + TREE_CHAIN (prev) = TREE_CHAIN (x); + } + } + else + { + if (DECL_NAME (field) == DECL_NAME (x)) + { + if (TREE_CODE (field) == CONST_DECL + && TREE_CODE (x) == CONST_DECL) + cp_error_at ("duplicate enum value `%D'", x); + else if (TREE_CODE (field) == CONST_DECL + || TREE_CODE (x) == CONST_DECL) + cp_error_at ("duplicate field `%D' (as enum and non-enum)", + x); + else if (DECL_DECLARES_TYPE_P (field) + && DECL_DECLARES_TYPE_P (x)) + { + if (same_type_p (TREE_TYPE (field), TREE_TYPE (x))) + continue; + cp_error_at ("duplicate nested type `%D'", x); + } + else if (DECL_DECLARES_TYPE_P (field) + || DECL_DECLARES_TYPE_P (x)) + { + /* Hide tag decls. */ + if ((TREE_CODE (field) == TYPE_DECL + && DECL_ARTIFICIAL (field)) + || (TREE_CODE (x) == TYPE_DECL + && DECL_ARTIFICIAL (x))) + continue; + cp_error_at ("duplicate field `%D' (as type and non-type)", + x); + } + else + cp_error_at ("duplicate member `%D'", x); + if (prev == 0) + fields = TREE_CHAIN (fields); + else + TREE_CHAIN (prev) = TREE_CHAIN (x); + } + } + } + } + return fields; +} + +static void +delete_duplicate_fields (fields) + tree fields; +{ + tree x; + for (x = fields; x && TREE_CHAIN (x); x = TREE_CHAIN (x)) + TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x)); +} + +/* Change the access of FDECL to ACCESS in T. The access to FDECL is + along the path given by BINFO. Return 1 if change was legit, + otherwise return 0. */ + +static int +alter_access (t, binfo, fdecl, access) + tree t; + tree binfo; + tree fdecl; + tree access; +{ + tree elem = purpose_member (t, DECL_ACCESS (fdecl)); + if (elem) + { + if (TREE_VALUE (elem) != access) + { + if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL) + cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl)); + else + error ("conflicting access specifications for field `%s', ignored", + IDENTIFIER_POINTER (DECL_NAME (fdecl))); + } + else + { + /* They're changing the access to the same thing they changed + it to before. That's OK. */ + ; + } + } + else + { + enforce_access (binfo, fdecl); + DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl)); + return 1; + } + return 0; +} + +/* Process the USING_DECL, which is a member of T. The METHOD_VEC, if + non-NULL, is the methods of T. The FIELDS are the fields of T. */ + +static void +handle_using_decl (using_decl, t, method_vec, fields) + tree using_decl; + tree t; + tree method_vec; + tree fields; +{ + tree ctype = DECL_INITIAL (using_decl); + tree name = DECL_NAME (using_decl); + tree access + = TREE_PRIVATE (using_decl) ? access_private_node + : TREE_PROTECTED (using_decl) ? access_protected_node + : access_public_node; + tree fdecl, binfo; + tree flist = NULL_TREE; + tree tmp; + int i; + int n_methods; + + binfo = binfo_or_else (ctype, t); + if (! binfo) + return; + + if (name == constructor_name (ctype) + || name == constructor_name_full (ctype)) + { + cp_error_at ("using-declaration for constructor", using_decl); + return; + } + + fdecl = lookup_member (binfo, name, 0, 0); + + if (!fdecl) + { + cp_error_at ("no members matching `%D' in `%#T'", using_decl, ctype); + return; + } + + /* Functions are represented as TREE_LIST, with the purpose + being the type and the value the functions. Other members + come as themselves. */ + if (TREE_CODE (fdecl) == TREE_LIST) + /* Ignore base type this came from. */ + fdecl = TREE_VALUE (fdecl); + + if (TREE_CODE (fdecl) == OVERLOAD) + { + /* We later iterate over all functions. */ + flist = fdecl; + fdecl = OVL_FUNCTION (flist); + } + + name = DECL_NAME (fdecl); + n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; + for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); i++) + if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i))) + == name) + { + cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); + cp_error_at (" because of local method `%#D' with same name", + OVL_CURRENT (TREE_VEC_ELT (method_vec, i))); + return; + } + + if (! DECL_LANG_SPECIFIC (fdecl)) + /* We don't currently handle DECL_ACCESS for TYPE_DECLs; just return. */ + return; + + for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp)) + if (DECL_NAME (tmp) == name) + { + cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); + cp_error_at (" because of local field `%#D' with same name", tmp); + return; + } + + /* Make type T see field decl FDECL with access ACCESS.*/ + if (flist) + { + while (flist) + { + if (alter_access (t, binfo, OVL_FUNCTION (flist), + access) == 0) + return; + flist = OVL_CHAIN (flist); + } + } + else + alter_access (t, binfo, fdecl, access); +} + +struct base_info +{ + int has_virtual; + int max_has_virtual; + tree vfield; + tree vfields; + tree rtti; + char cant_have_default_ctor; + char cant_have_const_ctor; + char no_const_asn_ref; +}; + +/* Record information about type T derived from its base classes. + Store most of that information in T itself, and place the + remaining information in the struct BASE_INFO. + + Propagate basetype offsets throughout the lattice. Note that the + lattice topped by T is really a pair: it's a DAG that gives the + structure of the derivation hierarchy, and it's a list of the + virtual baseclasses that appear anywhere in the DAG. When a vbase + type appears in the DAG, it's offset is 0, and it's children start + their offsets from that point. When a vbase type appears in the list, + its offset is the offset it has in the hierarchy, and its children's + offsets include that offset in theirs. + + Returns the index of the first base class to have virtual functions, + or -1 if no such base class. */ + +static int +finish_base_struct (t, b) + tree t; + struct base_info *b; +{ + tree binfos = TYPE_BINFO_BASETYPES (t); + int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; + int first_vfn_base_index = -1; + bzero ((char *) b, sizeof (struct base_info)); + + for (i = 0; i < n_baseclasses; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree basetype = BINFO_TYPE (base_binfo); + + /* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P + here because the case of virtual functions but non-virtual + dtor is handled in finish_struct_1. */ + if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype) + && TYPE_HAS_DESTRUCTOR (basetype)) + cp_warning ("base class `%#T' has a non-virtual destructor", basetype); + + /* If the type of basetype is incomplete, then + we already complained about that fact + (and we should have fixed it up as well). */ + if (TYPE_SIZE (basetype) == 0) + { + int j; + /* The base type is of incomplete type. It is + probably best to pretend that it does not + exist. */ + if (i == n_baseclasses-1) + TREE_VEC_ELT (binfos, i) = NULL_TREE; + TREE_VEC_LENGTH (binfos) -= 1; + n_baseclasses -= 1; + for (j = i; j+1 < n_baseclasses; j++) + TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1); + } + + if (! TYPE_HAS_CONST_INIT_REF (basetype)) + b->cant_have_const_ctor = 1; + + if (TYPE_HAS_CONSTRUCTOR (basetype) + && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)) + { + b->cant_have_default_ctor = 1; + if (! TYPE_HAS_CONSTRUCTOR (t)) + { + cp_pedwarn ("base `%T' with only non-default constructor", + basetype); + cp_pedwarn ("in class without a constructor"); + } + } + + if (TYPE_HAS_ASSIGN_REF (basetype) + && !TYPE_HAS_CONST_ASSIGN_REF (basetype)) + b->no_const_asn_ref = 1; + + TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype); + TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype); + TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype); + TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype); + + TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype); + TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype); + TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype); + + if (CLASSTYPE_COM_INTERFACE (basetype)) + { + CLASSTYPE_COM_INTERFACE (t) = 1; + if (i > 0) + cp_error + ("COM interface type `%T' must be the leftmost base class", + basetype); + } + else if (CLASSTYPE_COM_INTERFACE (t)) + { + cp_error ("COM interface type `%T' with non-COM base class `%T'", + t, basetype); + CLASSTYPE_COM_INTERFACE (t) = 0; + } + + if (TYPE_VIRTUAL_P (basetype)) + { + /* Ensure that this is set from at least a virtual base + class. */ + if (b->rtti == NULL_TREE) + b->rtti = CLASSTYPE_RTTI (basetype); + + /* Don't borrow virtuals from virtual baseclasses. */ + if (TREE_VIA_VIRTUAL (base_binfo)) + continue; + + if (first_vfn_base_index < 0) + { + tree vfields; + first_vfn_base_index = i; + + /* Update these two, now that we know what vtable we are + going to extend. This is so that we can add virtual + functions, and override them properly. */ + TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); + TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); + b->has_virtual = CLASSTYPE_VSIZE (basetype); + b->vfield = CLASSTYPE_VFIELD (basetype); + b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype)); + vfields = b->vfields; + while (vfields) + { + if (VF_BINFO_VALUE (vfields) == NULL_TREE + || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))) + { + tree value = VF_BASETYPE_VALUE (vfields); + if (DECL_NAME (CLASSTYPE_VFIELD (value)) + == DECL_NAME (CLASSTYPE_VFIELD (basetype))) + VF_NORMAL_VALUE (b->vfields) = basetype; + else + VF_NORMAL_VALUE (b->vfields) = VF_NORMAL_VALUE (vfields); + } + vfields = TREE_CHAIN (vfields); + } + CLASSTYPE_VFIELD (t) = b->vfield; + } + else + { + /* Only add unique vfields, and flatten them out as we go. */ + tree vfields = CLASSTYPE_VFIELDS (basetype); + while (vfields) + { + if (VF_BINFO_VALUE (vfields) == NULL_TREE + || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))) + { + tree value = VF_BASETYPE_VALUE (vfields); + b->vfields = tree_cons (base_binfo, value, b->vfields); + if (DECL_NAME (CLASSTYPE_VFIELD (value)) + == DECL_NAME (CLASSTYPE_VFIELD (basetype))) + VF_NORMAL_VALUE (b->vfields) = basetype; + else + VF_NORMAL_VALUE (b->vfields) = VF_NORMAL_VALUE (vfields); + } + vfields = TREE_CHAIN (vfields); + } + + if (b->has_virtual == 0) + { + first_vfn_base_index = i; + + /* Update these two, now that we know what vtable we are + going to extend. This is so that we can add virtual + functions, and override them properly. */ + TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); + TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); + b->has_virtual = CLASSTYPE_VSIZE (basetype); + b->vfield = CLASSTYPE_VFIELD (basetype); + CLASSTYPE_VFIELD (t) = b->vfield; + /* When we install the first one, set the VF_NORMAL_VALUE + to be the current class, as this it is the most derived + class. Hopefully, this is not set to something else + later. (mrs) */ + vfields = b->vfields; + while (vfields) + { + if (DECL_NAME (CLASSTYPE_VFIELD (t)) + == DECL_NAME (CLASSTYPE_VFIELD (basetype))) + { + VF_NORMAL_VALUE (vfields) = t; + /* There should only be one of them! And it should + always be found, if we get into here. (mrs) */ + break; + } + vfields = TREE_CHAIN (vfields); + } + } + } + } + } + + { + tree vfields; + /* Find the base class with the largest number of virtual functions. */ + for (vfields = b->vfields; vfields; vfields = TREE_CHAIN (vfields)) + { + if (CLASSTYPE_VSIZE (VF_BASETYPE_VALUE (vfields)) > b->max_has_virtual) + b->max_has_virtual = CLASSTYPE_VSIZE (VF_BASETYPE_VALUE (vfields)); + if (VF_DERIVED_VALUE (vfields) + && CLASSTYPE_VSIZE (VF_DERIVED_VALUE (vfields)) > b->max_has_virtual) + b->max_has_virtual = CLASSTYPE_VSIZE (VF_DERIVED_VALUE (vfields)); + } + } + + if (b->vfield == 0) + /* If all virtual functions come only from virtual baseclasses. */ + return -1; + + /* Update the rtti base if we have a non-virtual base class version + of it. */ + b->rtti = CLASSTYPE_RTTI (BINFO_TYPE (TREE_VEC_ELT (binfos, first_vfn_base_index))); + + return first_vfn_base_index; +} + +/* Set memoizing fields and bits of T (and its variants) for later use. + MAX_HAS_VIRTUAL is the largest size of any T's virtual function tables. */ + +static void +finish_struct_bits (t, max_has_virtual) + tree t; + int max_has_virtual; +{ + int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); + + /* Fix up variants (if any). */ + tree variants = TYPE_NEXT_VARIANT (t); + while (variants) + { + /* These fields are in the _TYPE part of the node, not in + the TYPE_LANG_SPECIFIC component, so they are not shared. */ + TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t); + TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t); + TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t); + TYPE_NEEDS_DESTRUCTOR (variants) = TYPE_NEEDS_DESTRUCTOR (t); + + TYPE_USES_COMPLEX_INHERITANCE (variants) = TYPE_USES_COMPLEX_INHERITANCE (t); + TYPE_VIRTUAL_P (variants) = TYPE_VIRTUAL_P (t); + TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t); + TYPE_USES_PVBASES (variants) = TYPE_USES_PVBASES (t); + /* Copy whatever these are holding today. */ + TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t); + TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t); + TYPE_FIELDS (variants) = TYPE_FIELDS (t); + TYPE_SIZE (variants) = TYPE_SIZE (t); + TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t); + variants = TYPE_NEXT_VARIANT (variants); + } + + if (n_baseclasses && max_has_virtual) + { + /* For a class w/o baseclasses, `finish_struct' has set + CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by definition). Similarly + for a class who's base classes do not have vtables. When neither + of these is true, we might have removed abstract virtuals (by + providing a definition), added some (by declaring new ones), or + redeclared ones from a base class. We need to recalculate what's + really an abstract virtual at this point (by looking in the + vtables). */ + CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t); + } + + if (n_baseclasses) + { + /* Notice whether this class has type conversion functions defined. */ + tree binfo = TYPE_BINFO (t); + tree binfos = BINFO_BASETYPES (binfo); + tree basetype; + + for (i = n_baseclasses-1; i >= 0; i--) + { + basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); + + TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype); + } + } + + /* If this type has a copy constructor, force its mode to be BLKmode, and + force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to + be passed by invisible reference and prevent it from being returned in + a register. + + Also do this if the class has BLKmode but can still be returned in + registers, since function_cannot_inline_p won't let us inline + functions returning such a type. This affects the HP-PA. */ + if (! TYPE_HAS_TRIVIAL_INIT_REF (t) + || (TYPE_MODE (t) == BLKmode && ! aggregate_value_p (t) + && CLASSTYPE_NON_AGGREGATE (t))) + { + tree variants; + DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode; + for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants)) + { + TYPE_MODE (variants) = BLKmode; + TREE_ADDRESSABLE (variants) = 1; + } + } +} + +/* Issue warnings about T having private constructors, but no friends, + and so forth. + + HAS_NONPRIVATE_METHOD is nonzero if T has any non-private methods or + static members. HAS_NONPRIVATE_STATIC_FN is nonzero if T has any + non-private static member functions. */ + +static void +maybe_warn_about_overly_private_class (t) + tree t; +{ + int has_member_fn = 0; + int has_nonprivate_method = 0; + tree fn; + + if (!warn_ctor_dtor_privacy + /* If the class has friends, those entities might create and + access instances, so we should not warn. */ + || (CLASSTYPE_FRIEND_CLASSES (t) + || DECL_FRIENDLIST (TYPE_MAIN_DECL (t))) + /* We will have warned when the template was declared; there's + no need to warn on every instantiation. */ + || CLASSTYPE_TEMPLATE_INSTANTIATION (t)) + /* There's no reason to even consider warning about this + class. */ + return; + + /* We only issue one warning, if more than one applies, because + otherwise, on code like: + + class A { + // Oops - forgot `public:' + A(); + A(const A&); + ~A(); + }; + + we warn several times about essentially the same problem. */ + + /* Check to see if all (non-constructor, non-destructor) member + functions are private. (Since there are no friends or + non-private statics, we can't ever call any of the private member + functions.) */ + for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn)) + /* We're not interested in compiler-generated methods; they don't + provide any way to call private members. */ + if (!DECL_ARTIFICIAL (fn)) + { + if (!TREE_PRIVATE (fn)) + { + if (DECL_STATIC_FUNCTION_P (fn)) + /* A non-private static member function is just like a + friend; it can create and invoke private member + functions, and be accessed without a class + instance. */ + return; + + has_nonprivate_method = 1; + break; + } + else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn)) + has_member_fn = 1; + } + + if (!has_nonprivate_method && has_member_fn) + { + /* There are no non-private methods, and there's at least one + private member function that isn't a constructor or + destructor. (If all the private members are + constructors/destructors we want to use the code below that + issues error messages specifically referring to + constructors/destructors.) */ + int i; + tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); + for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++) + if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i)) + || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i))) + { + has_nonprivate_method = 1; + break; + } + if (!has_nonprivate_method) + { + cp_warning ("all member functions in class `%T' are private", t); + return; + } + } + + /* Even if some of the member functions are non-private, the class + won't be useful for much if all the constructors or destructors + are private: such an object can never be created or destroyed. */ + if (TYPE_HAS_DESTRUCTOR (t)) + { + tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1); + + if (TREE_PRIVATE (dtor)) + { + cp_warning ("`%#T' only defines a private destructor and has no friends", + t); + return; + } + } + + if (TYPE_HAS_CONSTRUCTOR (t)) + { + int nonprivate_ctor = 0; + + /* If a non-template class does not define a copy + constructor, one is defined for it, enabling it to avoid + this warning. For a template class, this does not + happen, and so we would normally get a warning on: + + template class C { private: C(); }; + + To avoid this asymmetry, we check TYPE_HAS_INIT_REF. All + complete non-template or fully instantiated classes have this + flag set. */ + if (!TYPE_HAS_INIT_REF (t)) + nonprivate_ctor = 1; + else + for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); + fn; + fn = OVL_NEXT (fn)) + { + tree ctor = OVL_CURRENT (fn); + /* Ideally, we wouldn't count copy constructors (or, in + fact, any constructor that takes an argument of the + class type as a parameter) because such things cannot + be used to construct an instance of the class unless + you already have one. But, for now at least, we're + more generous. */ + if (! TREE_PRIVATE (ctor)) + { + nonprivate_ctor = 1; + break; + } + } + + if (nonprivate_ctor == 0) + { + cp_warning ("`%#T' only defines private constructors and has no friends", + t); + return; + } + } +} + + +/* Warn about duplicate methods in fn_fields. Also compact method + lists so that lookup can be made faster. + + Data Structure: List of method lists. The outer list is a + TREE_LIST, whose TREE_PURPOSE field is the field name and the + TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN + links the entire list of methods for TYPE_METHODS. Friends are + chained in the same way as member functions (? TREE_CHAIN or + DECL_CHAIN), but they live in the TREE_TYPE field of the outer + list. That allows them to be quickly deleted, and requires no + extra storage. + + If there are any constructors/destructors, they are moved to the + front of the list. This makes pushclass more efficient. + + We also link each field which has shares a name with its baseclass + to the head of the list of fields for that base class. This allows + us to reduce search time in places like `build_method_call' to + consider only reasonably likely functions. */ + +static void +finish_struct_methods (t) + tree t; +{ + tree fn_fields; + tree method_vec = CLASSTYPE_METHOD_VEC (t); + tree ctor_name = constructor_name (t); + + /* First fill in entry 0 with the constructors, entry 1 with destructors, + and the next few with type conversion operators (if any). */ + for (fn_fields = TYPE_METHODS (t); fn_fields; + fn_fields = TREE_CHAIN (fn_fields)) + { + tree fn_name = DECL_NAME (fn_fields); + + /* Clear out this flag. + + @@ Doug may figure out how to break + @@ this with nested classes and friends. */ + DECL_IN_AGGR_P (fn_fields) = 0; + + /* Note here that a copy ctor is private, so we don't dare generate + a default copy constructor for a class that has a member + of this type without making sure they have access to it. */ + if (fn_name == ctor_name) + { + tree parmtypes = FUNCTION_ARG_CHAIN (fn_fields); + tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node; + + if (TREE_CODE (parmtype) == REFERENCE_TYPE + && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t) + { + if (TREE_CHAIN (parmtypes) == NULL_TREE + || TREE_CHAIN (parmtypes) == void_list_node + || TREE_PURPOSE (TREE_CHAIN (parmtypes))) + { + if (TREE_PROTECTED (fn_fields)) + TYPE_HAS_NONPUBLIC_CTOR (t) = 1; + else if (TREE_PRIVATE (fn_fields)) + TYPE_HAS_NONPUBLIC_CTOR (t) = 2; + } + } + } + else if (fn_name == ansi_opname[(int) MODIFY_EXPR]) + { + tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields)); + + if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields))) + { + if (TREE_PROTECTED (fn_fields)) + TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1; + else if (TREE_PRIVATE (fn_fields)) + TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 2; + } + } + } + + if (TYPE_HAS_DESTRUCTOR (t) && !TREE_VEC_ELT (method_vec, 1)) + /* We thought there was a destructor, but there wasn't. Some + parse errors cause this anomalous situation. */ + TYPE_HAS_DESTRUCTOR (t) = 0; + + /* Issue warnings about private constructors and such. If there are + no methods, then some public defaults are generated. */ + maybe_warn_about_overly_private_class (t); +} + +/* Emit error when a duplicate definition of a type is seen. Patch up. */ + +void +duplicate_tag_error (t) + tree t; +{ + cp_error ("redefinition of `%#T'", t); + cp_error_at ("previous definition here", t); + + /* Pretend we haven't defined this type. */ + + /* All of the component_decl's were TREE_CHAINed together in the parser. + finish_struct_methods walks these chains and assembles all methods with + the same base name into DECL_CHAINs. Now we don't need the parser chains + anymore, so we unravel them. */ + + /* This used to be in finish_struct, but it turns out that the + TREE_CHAIN is used by dbxout_type_methods and perhaps some other + things... */ + if (CLASSTYPE_METHOD_VEC (t)) + { + tree method_vec = CLASSTYPE_METHOD_VEC (t); + int i, len = TREE_VEC_LENGTH (method_vec); + for (i = 0; i < len; i++) + { + tree unchain = TREE_VEC_ELT (method_vec, i); + while (unchain != NULL_TREE) + { + TREE_CHAIN (OVL_CURRENT (unchain)) = NULL_TREE; + unchain = OVL_NEXT (unchain); + } + } + } + + if (TYPE_LANG_SPECIFIC (t)) + { + tree binfo = TYPE_BINFO (t); + int interface_only = CLASSTYPE_INTERFACE_ONLY (t); + int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t); + + bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type)); + BINFO_BASETYPES(binfo) = NULL_TREE; + + TYPE_BINFO (t) = binfo; + CLASSTYPE_INTERFACE_ONLY (t) = interface_only; + SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown); + TYPE_REDEFINED (t) = 1; + } + TYPE_SIZE (t) = NULL_TREE; + TYPE_MODE (t) = VOIDmode; + TYPE_FIELDS (t) = NULL_TREE; + TYPE_METHODS (t) = NULL_TREE; + TYPE_VFIELD (t) = NULL_TREE; + TYPE_CONTEXT (t) = NULL_TREE; +} + +/* finish up all new vtables. */ + +static void +finish_vtbls (binfo, do_self, t) + tree binfo; + int do_self; + tree t; +{ + tree binfos = BINFO_BASETYPES (binfo); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + /* Should we use something besides CLASSTYPE_VFIELDS? */ + if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) + { + if (BINFO_NEW_VTABLE_MARKED (binfo)) + { + tree decl, context; + + decl = BINFO_VTABLE (binfo); + context = DECL_CONTEXT (decl); + DECL_CONTEXT (decl) = 0; + if (DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo)) + DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, + BINFO_VIRTUALS (binfo)); + cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0); + DECL_CONTEXT (decl) = context; + } + CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); + } + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + if (TREE_VIA_VIRTUAL (base_binfo)) + { + base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t)); + } + finish_vtbls (base_binfo, is_not_base_vtable, t); + } +} + +/* True if we should override the given BASE_FNDECL with the given + FNDECL. */ + +static int +overrides (fndecl, base_fndecl) + tree fndecl, base_fndecl; +{ + /* Destructors have special names. */ + if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) + && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) + return 1; + if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) + || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) + return 0; + if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl)) + { + tree types, base_types; +#if 0 + retypes = TREE_TYPE (TREE_TYPE (fndecl)); + base_retypes = TREE_TYPE (TREE_TYPE (base_fndecl)); +#endif + types = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl)); + if ((TYPE_QUALS (TREE_TYPE (TREE_VALUE (base_types))) + == TYPE_QUALS (TREE_TYPE (TREE_VALUE (types)))) + && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types))) + return 1; + } + return 0; +} + +static tree +get_class_offset_1 (parent, binfo, context, t, fndecl) + tree parent, binfo, context, t, fndecl; +{ + tree binfos = BINFO_BASETYPES (binfo); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + tree rval = NULL_TREE; + + if (binfo == parent) + return error_mark_node; + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree nrval; + + if (TREE_VIA_VIRTUAL (base_binfo)) + base_binfo = binfo_member (BINFO_TYPE (base_binfo), + CLASSTYPE_VBASECLASSES (t)); + nrval = get_class_offset_1 (parent, base_binfo, context, t, fndecl); + /* See if we have a new value */ + if (nrval && (nrval != error_mark_node || rval==0)) + { + /* Only compare if we have two offsets */ + if (rval && rval != error_mark_node + && ! tree_int_cst_equal (nrval, rval)) + { + /* Only give error if the two offsets are different */ + error ("every virtual function must have a unique final overrider"); + cp_error (" found two (or more) `%T' class subobjects in `%T'", context, t); + cp_error (" with virtual `%D' from virtual base class", fndecl); + return rval; + } + rval = nrval; + } + + if (rval && BINFO_TYPE (binfo) == context) + { + my_friendly_assert (rval == error_mark_node + || tree_int_cst_equal (rval, BINFO_OFFSET (binfo)), 999); + rval = BINFO_OFFSET (binfo); + } + } + return rval; +} + +/* Get the offset to the CONTEXT subobject that is related to the + given BINFO. */ + +static tree +get_class_offset (context, t, binfo, fndecl) + tree context, t, binfo, fndecl; +{ + tree first_binfo = binfo; + tree offset; + int i; + + if (context == t) + return integer_zero_node; + + if (BINFO_TYPE (binfo) == context) + return BINFO_OFFSET (binfo); + + /* Check less derived binfos first. */ + while (BINFO_BASETYPES (binfo) + && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) + { + tree binfos = BINFO_BASETYPES (binfo); + binfo = TREE_VEC_ELT (binfos, i); + if (BINFO_TYPE (binfo) == context) + return BINFO_OFFSET (binfo); + } + + /* Ok, not found in the less derived binfos, now check the more + derived binfos. */ + offset = get_class_offset_1 (first_binfo, TYPE_BINFO (t), context, t, fndecl); + if (offset==0 || TREE_CODE (offset) != INTEGER_CST) + my_friendly_abort (999); /* we have to find it. */ + return offset; +} + +/* Skip RTTI information at the front of the virtual list. */ + +unsigned HOST_WIDE_INT +skip_rtti_stuff (virtuals, t) + tree *virtuals, t; +{ + int n; + + if (CLASSTYPE_COM_INTERFACE (t)) + return 0; + + n = 0; + if (*virtuals) + { + /* We always reserve a slot for the offset/tdesc entry. */ + ++n; + *virtuals = TREE_CHAIN (*virtuals); + } + if (flag_vtable_thunks && *virtuals) + { + /* The second slot is reserved for the tdesc pointer when thunks + are used. */ + ++n; + *virtuals = TREE_CHAIN (*virtuals); + } + return n; +} + +static void +modify_one_vtable (binfo, t, fndecl, pfn) + tree binfo, t, fndecl, pfn; +{ + tree virtuals = BINFO_VIRTUALS (binfo); + unsigned HOST_WIDE_INT n; + + /* update rtti entry */ + if (flag_rtti) + { + if (binfo == TYPE_BINFO (t)) + { + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + build_vtable (TYPE_BINFO (DECL_CONTEXT (CLASSTYPE_VFIELD (t))), t); + } + else + { + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + prepare_fresh_vtable (binfo, t); + } + } + if (fndecl == NULL_TREE) + return; + + n = skip_rtti_stuff (&virtuals, t); + + while (virtuals) + { + tree current_fndecl = TREE_VALUE (virtuals); + current_fndecl = FNADDR_FROM_VTABLE_ENTRY (current_fndecl); + current_fndecl = TREE_OPERAND (current_fndecl, 0); + if (current_fndecl && overrides (fndecl, current_fndecl)) + { + tree base_offset, offset; + tree context = DECL_CLASS_CONTEXT (fndecl); + tree vfield = CLASSTYPE_VFIELD (t); + tree this_offset; + + offset = get_class_offset (context, t, binfo, fndecl); + + /* Find the right offset for the this pointer based on the + base class we just found. We have to take into + consideration the virtual base class pointers that we + stick in before the virtual function table pointer. + + Also, we want just the delta between the most base class + that we derived this vfield from and us. */ + base_offset = size_binop (PLUS_EXPR, + get_derived_offset (binfo, DECL_CONTEXT (current_fndecl)), + BINFO_OFFSET (binfo)); + this_offset = ssize_binop (MINUS_EXPR, offset, base_offset); + + if (binfo == TYPE_BINFO (t)) + { + /* In this case, it is *type*'s vtable we are modifying. + We start with the approximation that it's vtable is that + of the immediate base class. */ + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t); + } + else + { + /* This is our very own copy of `basetype' to play with. + Later, we will fill in all the virtual functions + that override the virtual functions in these base classes + which are not defined by the current type. */ + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + prepare_fresh_vtable (binfo, t); + } + +#ifdef NOTQUITE + cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo))); +#endif + modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n), + build_vtable_entry (this_offset, pfn), + fndecl); + } + ++n; + virtuals = TREE_CHAIN (virtuals); + } +} + +/* These are the ones that are not through virtual base classes. */ + +static void +modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn) + tree binfo; + int do_self; + tree t, fndecl, pfn; +{ + tree binfos = BINFO_BASETYPES (binfo); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + /* Should we use something besides CLASSTYPE_VFIELDS? */ + if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) + { + modify_one_vtable (binfo, t, fndecl, pfn); + } + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + if (! TREE_VIA_VIRTUAL (base_binfo)) + modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl, pfn); + } +} + +/* Fixup all the delta entries in this one vtable that need updating. */ + +static void +fixup_vtable_deltas1 (binfo, t) + tree binfo, t; +{ + tree virtuals = BINFO_VIRTUALS (binfo); + unsigned HOST_WIDE_INT n; + + n = skip_rtti_stuff (&virtuals, t); + + while (virtuals) + { + tree fndecl = TREE_VALUE (virtuals); + tree pfn = FNADDR_FROM_VTABLE_ENTRY (fndecl); + tree delta = DELTA_FROM_VTABLE_ENTRY (fndecl); + fndecl = TREE_OPERAND (pfn, 0); + if (fndecl) + { + tree base_offset, offset; + tree context = DECL_CLASS_CONTEXT (fndecl); + tree vfield = CLASSTYPE_VFIELD (t); + tree this_offset; + + offset = get_class_offset (context, t, binfo, fndecl); + + /* Find the right offset for the this pointer based on the + base class we just found. We have to take into + consideration the virtual base class pointers that we + stick in before the virtual function table pointer. + + Also, we want just the delta between the most base class + that we derived this vfield from and us. */ + base_offset = size_binop (PLUS_EXPR, + get_derived_offset (binfo, + DECL_CONTEXT (fndecl)), + BINFO_OFFSET (binfo)); + this_offset = ssize_binop (MINUS_EXPR, offset, base_offset); + + if (! tree_int_cst_equal (this_offset, delta)) + { + /* Make sure we can modify the derived association with immunity. */ + if (binfo == TYPE_BINFO (t)) + { + /* In this case, it is *type*'s vtable we are modifying. + We start with the approximation that it's vtable is that + of the immediate base class. */ + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t); + } + else + { + /* This is our very own copy of `basetype' to play with. + Later, we will fill in all the virtual functions + that override the virtual functions in these base classes + which are not defined by the current type. */ + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + prepare_fresh_vtable (binfo, t); + } + + modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n), + build_vtable_entry (this_offset, pfn), + fndecl); + } + } + ++n; + virtuals = TREE_CHAIN (virtuals); + } +} + +/* Fixup all the delta entries in all the direct vtables that need updating. + This happens when we have non-overridden virtual functions from a + virtual base class, that are at a different offset, in the new + hierarchy, because the layout of the virtual bases has changed. */ + +static void +fixup_vtable_deltas (binfo, init_self, t) + tree binfo; + int init_self; + tree t; +{ + tree binfos = BINFO_BASETYPES (binfo); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + if (! TREE_VIA_VIRTUAL (base_binfo)) + fixup_vtable_deltas (base_binfo, is_not_base_vtable, t); + } + /* Should we use something besides CLASSTYPE_VFIELDS? */ + if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) + { + fixup_vtable_deltas1 (binfo, t); + } +} + +/* These are the ones that are through virtual base classes. */ + +static void +modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn) + tree binfo; + int do_self, via_virtual; + tree t, fndecl, pfn; +{ + tree binfos = BINFO_BASETYPES (binfo); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + /* Should we use something besides CLASSTYPE_VFIELDS? */ + if (do_self && via_virtual && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) + { + modify_one_vtable (binfo, t, fndecl, pfn); + } + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + if (TREE_VIA_VIRTUAL (base_binfo)) + { + via_virtual = 1; + base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t)); + } + modify_all_indirect_vtables (base_binfo, is_not_base_vtable, via_virtual, t, fndecl, pfn); + } +} + +static void +modify_all_vtables (t, fndecl, vfn) + tree t, fndecl, vfn; +{ + /* Do these first, so that we will make use of any non-virtual class's + vtable, over a virtual classes vtable. */ + modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl, vfn); + if (TYPE_USES_VIRTUAL_BASECLASSES (t)) + modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl, vfn); +} + +/* Here, we already know that they match in every respect. + All we have to check is where they had their declarations. */ + +static int +strictly_overrides (fndecl1, fndecl2) + tree fndecl1, fndecl2; +{ + int distance = get_base_distance (DECL_CLASS_CONTEXT (fndecl2), + DECL_CLASS_CONTEXT (fndecl1), + 0, (tree *)0); + if (distance == -2 || distance > 0) + return 1; + return 0; +} + +/* Merge overrides for one vtable. + If we want to merge in same function, we are fine. + else + if one has a DECL_CLASS_CONTEXT that is a parent of the + other, than choose the more derived one + else + potentially ill-formed (see 10.3 [class.virtual]) + we have to check later to see if there was an + override in this class. If there was ok, if not + then it is ill-formed. (mrs) + + We take special care to reuse a vtable, if we can. */ + +static void +override_one_vtable (binfo, old, t) + tree binfo, old, t; +{ + tree virtuals = BINFO_VIRTUALS (binfo); + tree old_virtuals = BINFO_VIRTUALS (old); + enum { REUSE_NEW, REUSE_OLD, UNDECIDED, NEITHER } choose = UNDECIDED; + + /* If we have already committed to modifying it, then don't try and + reuse another vtable. */ + if (BINFO_NEW_VTABLE_MARKED (binfo)) + choose = NEITHER; + + skip_rtti_stuff (&virtuals, t); + skip_rtti_stuff (&old_virtuals, t); + + while (virtuals) + { + tree fndecl = TREE_VALUE (virtuals); + tree old_fndecl = TREE_VALUE (old_virtuals); + fndecl = FNADDR_FROM_VTABLE_ENTRY (fndecl); + old_fndecl = FNADDR_FROM_VTABLE_ENTRY (old_fndecl); + fndecl = TREE_OPERAND (fndecl, 0); + old_fndecl = TREE_OPERAND (old_fndecl, 0); + /* First check to see if they are the same. */ + if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl)) + { + /* No need to do anything. */ + } + else if (strictly_overrides (fndecl, old_fndecl)) + { + if (choose == UNDECIDED) + choose = REUSE_NEW; + else if (choose == REUSE_OLD) + { + choose = NEITHER; + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + { + prepare_fresh_vtable (binfo, t); + override_one_vtable (binfo, old, t); + return; + } + } + } + else if (strictly_overrides (old_fndecl, fndecl)) + { + if (choose == UNDECIDED) + choose = REUSE_OLD; + else if (choose == REUSE_NEW) + { + choose = NEITHER; + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + { + prepare_fresh_vtable (binfo, t); + override_one_vtable (binfo, old, t); + return; + } + TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals); + } + else if (choose == NEITHER) + { + TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals); + } + } + else + { + choose = NEITHER; + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + { + prepare_fresh_vtable (binfo, t); + override_one_vtable (binfo, old, t); + return; + } + { + /* This MUST be overridden, or the class is ill-formed. */ + tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); + tree vfn; + + fndecl = copy_node (fndecl); + copy_lang_decl (fndecl); + DECL_NEEDS_FINAL_OVERRIDER_P (fndecl) = 1; + /* Make sure we search for it later. */ + if (! CLASSTYPE_ABSTRACT_VIRTUALS (t)) + CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node; + + vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl); + TREE_CONSTANT (vfn) = 1; + + /* We can use integer_zero_node, as we will core dump + if this is used anyway. */ + TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, vfn); + } + } + virtuals = TREE_CHAIN (virtuals); + old_virtuals = TREE_CHAIN (old_virtuals); + } + + /* Let's reuse the old vtable. */ + if (choose == REUSE_OLD) + { + BINFO_VTABLE (binfo) = BINFO_VTABLE (old); + BINFO_VIRTUALS (binfo) = BINFO_VIRTUALS (old); + } +} + +/* Merge in overrides for virtual bases. + BINFO is the hierarchy we want to modify, and OLD has the potential + overrides. */ + +static void +merge_overrides (binfo, old, do_self, t) + tree binfo, old; + int do_self; + tree t; +{ + tree binfos = BINFO_BASETYPES (binfo); + tree old_binfos = BINFO_BASETYPES (old); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + /* Should we use something besides CLASSTYPE_VFIELDS? */ + if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) + { + override_one_vtable (binfo, old, t); + } + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree old_base_binfo = TREE_VEC_ELT (old_binfos, i); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + if (! TREE_VIA_VIRTUAL (base_binfo)) + merge_overrides (base_binfo, old_base_binfo, is_not_base_vtable, t); + } +} + +/* Get the base virtual function declarations in T that are either + overridden or hidden by FNDECL as a list. We set TREE_PURPOSE with + the overrider/hider. */ + +static tree +get_basefndecls (fndecl, t) + tree fndecl, t; +{ + tree methods = TYPE_METHODS (t); + tree base_fndecls = NULL_TREE; + tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); + int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + while (methods) + { + if (TREE_CODE (methods) == FUNCTION_DECL + && DECL_VINDEX (methods) != NULL_TREE + && DECL_NAME (fndecl) == DECL_NAME (methods)) + base_fndecls = temp_tree_cons (fndecl, methods, base_fndecls); + + methods = TREE_CHAIN (methods); + } + + if (base_fndecls) + return base_fndecls; + + for (i = 0; i < n_baseclasses; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree basetype = BINFO_TYPE (base_binfo); + + base_fndecls = chainon (get_basefndecls (fndecl, basetype), + base_fndecls); + } + + return base_fndecls; +} + +/* Mark the functions that have been hidden with their overriders. + Since we start out with all functions already marked with a hider, + no need to mark functions that are just hidden. + + Subroutine of warn_hidden. */ + +static void +mark_overriders (fndecl, base_fndecls) + tree fndecl, base_fndecls; +{ + for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls)) + { + if (overrides (fndecl, TREE_VALUE (base_fndecls))) + TREE_PURPOSE (base_fndecls) = fndecl; + } +} + +/* If this declaration supersedes the declaration of + a method declared virtual in the base class, then + mark this field as being virtual as well. */ + +static void +check_for_override (decl, ctype) + tree decl, ctype; +{ + tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype)); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + int virtualp = DECL_VIRTUAL_P (decl); + int found_overriden_fn = 0; + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))) + { + tree tmp = get_matching_virtual + (base_binfo, decl, + DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))); + + if (tmp && !found_overriden_fn) + { + /* If this function overrides some virtual in some base + class, then the function itself is also necessarily + virtual, even if the user didn't explicitly say so. */ + DECL_VIRTUAL_P (decl) = 1; + + /* The TMP we really want is the one from the deepest + baseclass on this path, taking care not to + duplicate if we have already found it (via another + path to its virtual baseclass. */ + if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) + { + cp_error_at ("method `%D' may not be declared static", + decl); + cp_error_at ("(since `%D' declared virtual in base class.)", + tmp); + break; + } + virtualp = 1; + + DECL_VINDEX (decl) + = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl)); + + /* We now know that DECL overrides something, + which is all that is important. But, we must + continue to iterate through all the base-classes + in order to allow get_matching_virtual to check for + various illegal overrides. */ + found_overriden_fn = 1; + } + } + } + if (virtualp) + { + if (DECL_VINDEX (decl) == NULL_TREE) + DECL_VINDEX (decl) = error_mark_node; + IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; + } +} + +/* Warn about hidden virtual functions that are not overridden in t. + We know that constructors and destructors don't apply. */ + +void +warn_hidden (t) + tree t; +{ + tree method_vec = CLASSTYPE_METHOD_VEC (t); + int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; + int i; + + /* We go through each separately named virtual function. */ + for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); ++i) + { + tree fns = TREE_VEC_ELT (method_vec, i); + tree fndecl; + + tree base_fndecls = NULL_TREE; + tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); + int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + /* First see if we have any virtual functions in this batch. */ + for (; fns; fns = OVL_NEXT (fns)) + { + fndecl = OVL_CURRENT (fns); + if (DECL_VINDEX (fndecl)) + break; + } + + if (fns == NULL_TREE) + continue; + + /* First we get a list of all possible functions that might be + hidden from each base class. */ + for (i = 0; i < n_baseclasses; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree basetype = BINFO_TYPE (base_binfo); + + base_fndecls = chainon (get_basefndecls (fndecl, basetype), + base_fndecls); + } + + fns = OVL_NEXT (fns); + + /* ...then mark up all the base functions with overriders, preferring + overriders to hiders. */ + if (base_fndecls) + for (; fns; fns = OVL_NEXT (fns)) + { + fndecl = OVL_CURRENT (fns); + if (DECL_VINDEX (fndecl)) + mark_overriders (fndecl, base_fndecls); + } + + /* Now give a warning for all base functions without overriders, + as they are hidden. */ + for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls)) + { + if (! overrides (TREE_PURPOSE (base_fndecls), + TREE_VALUE (base_fndecls))) + { + /* Here we know it is a hider, and no overrider exists. */ + cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls)); + cp_warning_at (" by `%D'", TREE_PURPOSE (base_fndecls)); + } + } + } +} + +/* Generate one vtable for use in constructors or destructors of BASE + subobjects of COMPLETE_TYPE objects. The vtable belongs to the + vfield of the VBASEVASE subobject of the VBASE virtual base of + COMPLETE_TYPE (and BASE). */ + +static tree +finish_one_ctor_vtable (complete_type, base, vbase, vbasebase) + tree complete_type, base, vbase, vbasebase; +{ + tree virtuals; + tree newtable; + tree newvirtuals; + tree offset; + tree newvbase = binfo_member (BINFO_TYPE (vbase), + CLASSTYPE_VBASECLASSES (complete_type)); + + newtable = prepare_ctor_vtable (complete_type, base, vbasebase); + newvirtuals = copy_list (BINFO_VIRTUALS (vbasebase)); + + virtuals = newvirtuals; + /* Change the offset entry. First, delta between base an vbase. */ + offset = ssize_binop (MINUS_EXPR, BINFO_OFFSET (newvbase), + BINFO_OFFSET (base)); + /* Add delta between vbase and vbasebase. */ + offset = ssize_binop (PLUS_EXPR, offset, BINFO_OFFSET (vbasebase)); + offset = ssize_binop (MINUS_EXPR, offset, BINFO_OFFSET (vbase)); + /* Finally, negate. */ + offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset); + offset = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); + TREE_CONSTANT (offset) = 1; + TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, offset); + virtuals = TREE_CHAIN (virtuals); + + /* Skip the typeinfo function. */ + virtuals = TREE_CHAIN (virtuals); + + /* Iterate over all methods of this virtual base. */ + for (; virtuals; virtuals = TREE_CHAIN (virtuals)) + { + tree fndecl = TREE_VALUE (virtuals); + tree pfn = FNADDR_FROM_VTABLE_ENTRY (fndecl); + fndecl = TREE_OPERAND (pfn, 0); + if (fndecl) + { + tree delta, newdelta, binfo_context; + tree context = DECL_CLASS_CONTEXT (fndecl); + + /* If this method is implemented in a base of the vbase, the + thunk we have is correct. */ + if (DERIVED_FROM_P (context, vbase)) + continue; + + binfo_context = binfo_value (context, base); + if (TREE_VIA_VIRTUAL (binfo_context)) + binfo_context = binfo_member + (context, CLASSTYPE_VBASECLASSES (complete_type)); + /* This is the delta from a complete C to a B subobject, or + more generally to the base subobject that implements the + virtual function for B. BASE already has the offset to + the complete type. */ + delta = BINFO_OFFSET (binfo_context); + /* This is the delta from the A to the complete C. */ + newdelta = BINFO_OFFSET (newvbase); + /* This is the delta from the A to the B subobject. */ + newdelta = size_binop (MINUS_EXPR, newdelta, delta); + newdelta = ssize_binop (MINUS_EXPR, integer_zero_node, + newdelta); + + modify_vtable_entry (virtuals, + build_vtable_entry (newdelta, pfn), + fndecl); + } + } + DECL_INITIAL (newtable) = build_nt (CONSTRUCTOR, NULL_TREE, + newvirtuals); + DECL_CONTEXT (newtable) = NULL_TREE; + cp_finish_decl (newtable, DECL_INITIAL (newtable), NULL_TREE, 0, 0); + DECL_CONTEXT (newtable) = complete_type; + return newtable; +} + +/* Add all vtables into LIST for the VBASEBASE subobject and its bases + of VBASE virtual BASE of COMPLETE_TYPE for use in BASE + constructors. DO_SELF indicates whether this is the VBASEBASE that + has 'primary' vfield. Return the new LIST. */ + +static tree +prepend_ctor_vfields_for_vbase (complete_type, base, vbase, vbasebase, + do_self, list) + tree complete_type, base, vbase, vbasebase; + int do_self; + tree list; +{ + int i; + tree vtbl; + tree bases = BINFO_BASETYPES (vbasebase); + int vfp = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (vbasebase)); + + if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (vbasebase))) + { + vtbl = finish_one_ctor_vtable (complete_type, base, vbase, vbasebase); + vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl); + TREE_READONLY (vtbl) = 1; + TREE_CONSTANT (vtbl) = 1; + list = tree_cons (NULL_TREE, vtbl, list); + } + + if (!bases) + return list; + + for (i = 0; i < TREE_VEC_LENGTH (bases); i++) + { + tree vbasebase = TREE_VEC_ELT (bases, i); + if (TREE_VIA_VIRTUAL (vbasebase)) + continue; + list = prepend_ctor_vfields_for_vbase + (complete_type, base, vbase, vbasebase, (i != vfp), list); + } + + return list; +} + +/* Iterate over all virtual bases of the BASE subobject of + COMPLETE_TYPE. This list is given in VBASES. Return the list of + vtables generated in the process. */ + +static tree +finish_ctor_vtables_for_vbases (vbases, base, complete_type) + tree vbases, base, complete_type; +{ + tree result = NULL_TREE; + + for (; vbases; vbases = TREE_CHAIN (vbases)) + result = prepend_ctor_vfields_for_vbase + (complete_type, base, vbases, vbases, 1, result); + return result; +} + +/* Generate special vtables for virtual bases for use inside base + class ctors and dtors. Inside this function, we assume the + following scenario: + class A{virtual void foo();}; + class B:virtual A{int member1;} + class C:B{int member2;} + + BINFO is a base subject (e.g. B) of COMPLETE_TYPE. Returns the list + of virtual tables. */ + +static tree +finish_ctor_vtables_1 (binfo, complete_type) + tree binfo; + tree complete_type; +{ + int i; + tree binfos; + tree result = NULL_TREE; + + binfos = BINFO_BASETYPES (binfo); + if (!binfos) + return result; + + /* Iterate over all bases (i.e. B). */ + for (i = 0; i < TREE_VEC_LENGTH (binfos); i++) + { + tree base = TREE_VEC_ELT (binfos, i); + tree vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (base)); + if (!vbases) + /* This base class does not have virtual bases. */ + continue; + if (TREE_VIA_VIRTUAL (base)) + /* A virtual base class is initialized on in the most-derived + constructor. */ + continue; + if (!TYPE_USES_PVBASES (BINFO_TYPE (base))) + /* Class has no polymorphic vbases. */ + continue; + /* Prepend vtable list for base class. */ + result = chainon (finish_ctor_vtables_1 (base, complete_type), + result); + /* Prepend our own vtable list. */ + result = chainon + (finish_ctor_vtables_for_vbases (vbases, base, complete_type), + result); + } + return result; +} + +/* Add the vtables of a virtual base BINFO in front of LIST, returning + the new list. DO_SELF indicates whether we have to return the + vtable of a vfield borrowed in a derived class. */ + +static tree +prepend_vbase_vfields (binfo, do_self, list) + tree binfo; + int do_self; + tree list; +{ + int i; + tree vtbl; + tree bases = BINFO_BASETYPES (binfo); + int vfp = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + + if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) + { + vtbl = BINFO_VTABLE (binfo); + vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl); + TREE_READONLY (vtbl) = 1; + TREE_CONSTANT (vtbl) = 1; + list = tree_cons (NULL_TREE, vtbl, list); + } + + if (!bases) + return list; + + for (i = 0; i < TREE_VEC_LENGTH (bases); i++) + { + tree base = TREE_VEC_ELT (bases, i); + if (TREE_VIA_VIRTUAL (base)) + continue; + list = prepend_vbase_vfields (base, (i != vfp), list); + } + + return list; +} + +/* Wrapper around finish_ctor_vtables_1. Compute the vtable list for + type T. */ + +static void +finish_ctor_vtables (t) + tree t; +{ + tree veclist = NULL_TREE; + tree decl, type; + char *name; + tree vbase; + int len; + + /* This is only good for vtable thunks. */ + my_friendly_assert (flag_vtable_thunks, 990307); + + /* Start with the list of most-derived vtables. */ + + for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; + vbase = TREE_CHAIN (vbase)) + veclist = prepend_vbase_vfields (vbase, 1, veclist); + + /* Compute the list of vtables for the bases. */ + veclist = chainon (veclist, finish_ctor_vtables_1 (TYPE_BINFO (t), t)); + + /* Finally, we initialize the virtual bases first. */ + for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; + vbase = TREE_CHAIN (vbase)) + { + tree vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbase)); + if (!vbases) + continue; + veclist = chainon (veclist, + finish_ctor_vtables_for_vbases (vbases, vbase, t)); + veclist = chainon (veclist, + finish_ctor_vtables_1 (vbase, t)); + } + + veclist = nreverse (veclist); + + /* Generate the name for the vtable list. */ + name = alloca (strlen (VLIST_NAME_FORMAT) + + TYPE_ASSEMBLER_NAME_LENGTH (t) + 2); + sprintf (name, VLIST_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (t)); + + /* Build the type of the list. */ + len = list_length (veclist) - 1; + if (len < 0) + /* If this class has virtual bases without virtual methods, make a + single zero-entry in the array. This avoids zero-sized objects. */ + len++; + type = build_cplus_array_type (vtbl_ptr_type_node, + build_index_type (size_int (len))); + + + /* Produce a new decl holding the list. */ + decl = build_lang_decl (VAR_DECL, get_identifier (name), type); + TREE_STATIC (decl) = 1; + TREE_READONLY (decl) = 1; + decl = pushdecl_top_level (decl); + import_export_vtable (decl, t, 0); + DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, veclist); + + DECL_ARTIFICIAL (decl) = 1; + /* This tells finish_file et.al. that this is related to virtual + tables. There is currently no way to distinguish between vtables + and vlists, other than the name of the decl. */ + DECL_VIRTUAL_P (decl) = 1; + + /* Output the array. */ + cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0); + + /* Set the class context after finishing, so that finish thinks this + is an unrelated global, and then finish_vtable_vardecl knows what + class this is related to. */ + DECL_CONTEXT (decl) = t; +} + +/* Check for things that are invalid. There are probably plenty of other + things we should check for also. */ + +static void +finish_struct_anon (t) + tree t; +{ + tree field; + for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) + { + if (TREE_STATIC (field)) + continue; + if (TREE_CODE (field) != FIELD_DECL) + continue; + + if (DECL_NAME (field) == NULL_TREE + && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + { + tree* uelt = &TYPE_FIELDS (TREE_TYPE (field)); + for (; *uelt; uelt = &TREE_CHAIN (*uelt)) + { + if (DECL_ARTIFICIAL (*uelt)) + continue; + + if (DECL_NAME (*uelt) == constructor_name (t)) + cp_pedwarn_at ("ANSI C++ forbids member `%D' with same name as enclosing class", + *uelt); + + if (TREE_CODE (*uelt) != FIELD_DECL) + { + cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members", + *uelt); + continue; + } + + if (TREE_PRIVATE (*uelt)) + cp_pedwarn_at ("private member `%#D' in anonymous union", + *uelt); + else if (TREE_PROTECTED (*uelt)) + cp_pedwarn_at ("protected member `%#D' in anonymous union", + *uelt); + + TREE_PRIVATE (*uelt) = TREE_PRIVATE (field); + TREE_PROTECTED (*uelt) = TREE_PROTECTED (field); + } + } + } +} + +extern int interface_only, interface_unknown; + +/* Create default constructors, assignment operators, and so forth for + the type indicated by T, if they are needed. + CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and + CANT_HAVE_ASSIGNMENT are nonzero if, for whatever reason, the class + cannot have a default constructor, copy constructor taking a const + reference argument, or an assignment operator, respectively. If a + virtual destructor is created, its DECL is returned; otherwise the + return value is NULL_TREE. */ + +static tree +add_implicitly_declared_members (t, cant_have_default_ctor, + cant_have_const_cctor, + cant_have_assignment) + tree t; + int cant_have_default_ctor; + int cant_have_const_cctor; + int cant_have_assignment; +{ + tree default_fn; + tree implicit_fns = NULL_TREE; + tree name = TYPE_IDENTIFIER (t); + tree virtual_dtor = NULL_TREE; + tree *f; + + /* Destructor. */ + if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t) + && !IS_SIGNATURE (t)) + { + default_fn = cons_up_default_function (t, name, 0); + check_for_override (default_fn, t); + + /* If we couldn't make it work, then pretend we didn't need it. */ + if (default_fn == void_type_node) + TYPE_NEEDS_DESTRUCTOR (t) = 0; + else + { + TREE_CHAIN (default_fn) = implicit_fns; + implicit_fns = default_fn; + + if (DECL_VINDEX (default_fn)) + virtual_dtor = default_fn; + } + } + TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); + + /* Default constructor. */ + if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor + && ! IS_SIGNATURE (t)) + { + default_fn = cons_up_default_function (t, name, 2); + TREE_CHAIN (default_fn) = implicit_fns; + implicit_fns = default_fn; + } + + /* Copy constructor. */ + if (! TYPE_HAS_INIT_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t)) + { + /* ARM 12.18: You get either X(X&) or X(const X&), but + not both. --Chip */ + default_fn = cons_up_default_function (t, name, + 3 + cant_have_const_cctor); + TREE_CHAIN (default_fn) = implicit_fns; + implicit_fns = default_fn; + } + + /* Assignment operator. */ + if (! TYPE_HAS_ASSIGN_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t)) + { + default_fn = cons_up_default_function (t, name, + 5 + cant_have_assignment); + TREE_CHAIN (default_fn) = implicit_fns; + implicit_fns = default_fn; + } + + /* Now, hook all of the new functions on to TYPE_METHODS, + and add them to the CLASSTYPE_METHOD_VEC. */ + for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f)) + add_method (t, 0, *f); + *f = TYPE_METHODS (t); + TYPE_METHODS (t) = implicit_fns; + + return virtual_dtor; +} + +/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration + (or C++ class declaration). + + For C++, we must handle the building of derived classes. + Also, C++ allows static class members. The way that this is + handled is to keep the field name where it is (as the DECL_NAME + of the field), and place the overloaded decl in the DECL_FIELD_BITPOS + of the field. layout_record and layout_union will know about this. + + More C++ hair: inline functions have text in their + DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into + meaningful tree structure. After the struct has been laid out, set + things up so that this can happen. + + And still more: virtual functions. In the case of single inheritance, + when a new virtual function is seen which redefines a virtual function + from the base class, the new virtual function is placed into + the virtual function table at exactly the same address that + it had in the base class. When this is extended to multiple + inheritance, the same thing happens, except that multiple virtual + function tables must be maintained. The first virtual function + table is treated in exactly the same way as in the case of single + inheritance. Additional virtual function tables have different + DELTAs, which tell how to adjust `this' to point to the right thing. + + ATTRIBUTES is the set of decl attributes to be applied, if any. */ + +void +finish_struct_1 (t, warn_anon) + tree t; + int warn_anon; +{ + int old; + enum tree_code code = TREE_CODE (t); + tree fields = TYPE_FIELDS (t); + tree x, last_x, method_vec; + int has_virtual; + int max_has_virtual; + tree pending_virtuals = NULL_TREE; + tree pending_hard_virtuals = NULL_TREE; + tree abstract_virtuals = NULL_TREE; + tree vfield; + tree vfields; + tree virtual_dtor; + int cant_have_default_ctor; + int cant_have_const_ctor; + int no_const_asn_ref; + int has_mutable = 0; + + /* The index of the first base class which has virtual + functions. Only applied to non-virtual baseclasses. */ + int first_vfn_base_index; + + int n_baseclasses; + int any_default_members = 0; + int const_sans_init = 0; + int ref_sans_init = 0; + tree access_decls = NULL_TREE; + int aggregate = 1; + int empty = 1; + int has_pointers = 0; + tree inline_friends; + + if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) + pedwarn ("anonymous class type not used to declare any objects"); + + if (TYPE_SIZE (t)) + { + if (IS_AGGR_TYPE (t)) + cp_error ("redefinition of `%#T'", t); + else + my_friendly_abort (172); + popclass (); + return; + } + + GNU_xref_decl (current_function_decl, t); + + /* If this type was previously laid out as a forward reference, + make sure we lay it out again. */ + + TYPE_SIZE (t) = NULL_TREE; + CLASSTYPE_GOT_SEMICOLON (t) = 0; + +#if 0 + /* This is in general too late to do this. I moved the main case up to + left_curly, what else needs to move? */ + if (! IS_SIGNATURE (t)) + { + my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999); + my_friendly_assert (CLASSTYPE_INTERFACE_KNOWN (t) == ! interface_unknown, 999); + } +#endif + + old = suspend_momentary (); + + /* Install struct as DECL_FIELD_CONTEXT of each field decl. + Also process specified field sizes. + Set DECL_FIELD_SIZE to the specified size, or 0 if none specified. + The specified size is found in the DECL_INITIAL. + Store 0 there, except for ": 0" fields (so we can find them + and delete them, below). */ + + if (TYPE_BINFO_BASETYPES (t)) + n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t)); + else + n_baseclasses = 0; + + if (n_baseclasses > 0) + { + struct base_info base_info; + + first_vfn_base_index = finish_base_struct (t, &base_info); + /* Remember where we got our vfield from. */ + CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index; + has_virtual = base_info.has_virtual; + max_has_virtual = base_info.max_has_virtual; + vfield = base_info.vfield; + vfields = base_info.vfields; + CLASSTYPE_RTTI (t) = base_info.rtti; + cant_have_default_ctor = base_info.cant_have_default_ctor; + cant_have_const_ctor = base_info.cant_have_const_ctor; + no_const_asn_ref = base_info.no_const_asn_ref; + aggregate = 0; + } + else + { + first_vfn_base_index = -1; + has_virtual = 0; + max_has_virtual = has_virtual; + vfield = NULL_TREE; + vfields = NULL_TREE; + CLASSTYPE_RTTI (t) = NULL_TREE; + cant_have_default_ctor = 0; + cant_have_const_ctor = 0; + no_const_asn_ref = 0; + } + +#if 0 + /* Both of these should be done before now. */ + if (write_virtuals == 3 && CLASSTYPE_INTERFACE_KNOWN (t) + && ! IS_SIGNATURE (t)) + { + my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999); + my_friendly_assert (CLASSTYPE_VTABLE_NEEDS_WRITING (t) == ! interface_only, 999); + } +#endif + + /* The three of these are approximations which may later be + modified. Needed at this point to make add_virtual_function + and modify_vtable_entries work. */ + CLASSTYPE_VFIELDS (t) = vfields; + CLASSTYPE_VFIELD (t) = vfield; + + for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x)) + { + GNU_xref_member (current_class_name, x); + + /* If this was an evil function, don't keep it in class. */ + if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x))) + continue; + + /* Do both of these, even though they're in the same union; + if the insn `r' member and the size `i' member are + different sizes, as on the alpha, the larger of the two + will end up with garbage in it. */ + DECL_SAVED_INSNS (x) = NULL_RTX; + DECL_FIELD_SIZE (x) = 0; + + check_for_override (x, t); + if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x)) + cp_error_at ("initializer specified for non-virtual method `%D'", x); + + /* The name of the field is the original field name + Save this in auxiliary field for later overloading. */ + if (DECL_VINDEX (x)) + { + add_virtual_function (&pending_virtuals, &pending_hard_virtuals, + &has_virtual, x, t); + if (DECL_ABSTRACT_VIRTUAL_P (x)) + abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals); +#if 0 + /* XXX Why did I comment this out? (jason) */ + else + TREE_USED (x) = 1; +#endif + } + } + + if (n_baseclasses) + fields = chainon (build_vbase_pointer_fields (t), fields); + + last_x = NULL_TREE; + for (x = fields; x; x = TREE_CHAIN (x)) + { + GNU_xref_member (current_class_name, x); + + if (TREE_CODE (x) == FIELD_DECL) + { + DECL_PACKED (x) |= TYPE_PACKED (t); + + if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x))) + /* A zero-width bitfield doesn't do the trick. */; + else + empty = 0; + } + + if (TREE_CODE (x) == USING_DECL) + { + /* Save access declarations for later. */ + if (last_x) + TREE_CHAIN (last_x) = TREE_CHAIN (x); + else + fields = TREE_CHAIN (x); + + access_decls = scratch_tree_cons (NULL_TREE, x, access_decls); + continue; + } + + last_x = x; + + if (TREE_CODE (x) == TYPE_DECL + || TREE_CODE (x) == TEMPLATE_DECL) + continue; + + /* If we've gotten this far, it's a data member, possibly static, + or an enumerator. */ + + DECL_FIELD_CONTEXT (x) = t; + + /* ``A local class cannot have static data members.'' ARM 9.4 */ + if (current_function_decl && TREE_STATIC (x)) + cp_error_at ("field `%D' in local class cannot be static", x); + + /* Perform error checking that did not get done in + grokdeclarator. */ + if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE) + { + cp_error_at ("field `%D' invalidly declared function type", + x); + TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); + } + else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE) + { + cp_error_at ("field `%D' invalidly declared method type", x); + TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); + } + else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE) + { + cp_error_at ("field `%D' invalidly declared offset type", x); + TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); + } + +#if 0 + if (DECL_NAME (x) == constructor_name (t)) + cant_have_default_ctor = 1; +#endif + + if (TREE_TYPE (x) == error_mark_node) + continue; + + DECL_SAVED_INSNS (x) = NULL_RTX; + DECL_FIELD_SIZE (x) = 0; + + /* When this goes into scope, it will be a non-local reference. */ + DECL_NONLOCAL (x) = 1; + + if (TREE_CODE (x) == CONST_DECL) + continue; + + if (TREE_CODE (x) == VAR_DECL) + { + if (TREE_CODE (t) == UNION_TYPE) + /* Unions cannot have static members. */ + cp_error_at ("field `%D' declared static in union", x); + + continue; + } + + /* Now it can only be a FIELD_DECL. */ + + if (TREE_PRIVATE (x) || TREE_PROTECTED (x)) + aggregate = 0; + + /* If this is of reference type, check if it needs an init. + Also do a little ANSI jig if necessary. */ + if (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE) + { + if (DECL_INITIAL (x) == NULL_TREE) + ref_sans_init = 1; + + /* ARM $12.6.2: [A member initializer list] (or, for an + aggregate, initialization by a brace-enclosed list) is the + only way to initialize nonstatic const and reference + members. */ + cant_have_default_ctor = 1; + TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; + + if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings) + { + if (DECL_NAME (x)) + cp_warning_at ("non-static reference `%#D' in class without a constructor", x); + else + cp_warning_at ("non-static reference in class without a constructor", x); + } + } + + if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE) + has_pointers = 1; + + if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (TREE_TYPE (x))) + has_mutable = 1; + + /* If any field is const, the structure type is pseudo-const. */ + if (CP_TYPE_CONST_P (TREE_TYPE (x))) + { + C_TYPE_FIELDS_READONLY (t) = 1; + if (DECL_INITIAL (x) == NULL_TREE) + const_sans_init = 1; + + /* ARM $12.6.2: [A member initializer list] (or, for an + aggregate, initialization by a brace-enclosed list) is the + only way to initialize nonstatic const and reference + members. */ + cant_have_default_ctor = 1; + TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; + + if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t) + && extra_warnings) + { + if (DECL_NAME (x)) + cp_warning_at ("non-static const member `%#D' in class without a constructor", x); + else + cp_warning_at ("non-static const member in class without a constructor", x); + } + } + else + { + /* A field that is pseudo-const makes the structure + likewise. */ + tree t1 = TREE_TYPE (x); + while (TREE_CODE (t1) == ARRAY_TYPE) + t1 = TREE_TYPE (t1); + if (IS_AGGR_TYPE (t1)) + { + if (C_TYPE_FIELDS_READONLY (t1)) + C_TYPE_FIELDS_READONLY (t) = 1; + if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (t1)) + const_sans_init = 1; + } + } + + /* We set DECL_C_BIT_FIELD in grokbitfield. + If the type and width are valid, we'll also set DECL_BIT_FIELD. */ + if (DECL_C_BIT_FIELD (x)) + { + /* Invalid bit-field size done by grokfield. */ + /* Detect invalid bit-field type. */ + if (DECL_INITIAL (x) + && ! INTEGRAL_TYPE_P (TREE_TYPE (x))) + { + cp_error_at ("bit-field `%#D' with non-integral type", x); + DECL_INITIAL (x) = NULL; + } + + /* Detect and ignore out of range field width. */ + if (DECL_INITIAL (x)) + { + tree w = DECL_INITIAL (x); + register int width = 0; + + /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */ + STRIP_NOPS (w); + + /* detect invalid field size. */ + if (TREE_CODE (w) == CONST_DECL) + w = DECL_INITIAL (w); + else if (TREE_READONLY_DECL_P (w)) + w = decl_constant_value (w); + + if (TREE_CODE (w) != INTEGER_CST) + { + cp_error_at ("bit-field `%D' width not an integer constant", + x); + DECL_INITIAL (x) = NULL_TREE; + } + else if (width = TREE_INT_CST_LOW (w), + width < 0) + { + DECL_INITIAL (x) = NULL; + cp_error_at ("negative width in bit-field `%D'", x); + } + else if (width == 0 && DECL_NAME (x) != 0) + { + DECL_INITIAL (x) = NULL; + cp_error_at ("zero width for bit-field `%D'", x); + } + else if (width + > TYPE_PRECISION (long_long_unsigned_type_node)) + { + /* The backend will dump if you try to use something + too big; avoid that. */ + DECL_INITIAL (x) = NULL; + sorry ("bit-fields larger than %d bits", + TYPE_PRECISION (long_long_unsigned_type_node)); + cp_error_at (" in declaration of `%D'", x); + } + else if (width > TYPE_PRECISION (TREE_TYPE (x)) + && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE + && TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE) + { + cp_warning_at ("width of `%D' exceeds its type", x); + } + else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE + && ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))) > width) + || (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))) > width))) + { + cp_warning_at ("`%D' is too small to hold all values of `%#T'", + x, TREE_TYPE (x)); + } + + if (DECL_INITIAL (x)) + { + DECL_INITIAL (x) = NULL_TREE; + DECL_FIELD_SIZE (x) = width; + DECL_BIT_FIELD (x) = 1; + + if (width == 0) + { +#ifdef EMPTY_FIELD_BOUNDARY + DECL_ALIGN (x) = MAX (DECL_ALIGN (x), + EMPTY_FIELD_BOUNDARY); +#endif +#ifdef PCC_BITFIELD_TYPE_MATTERS + if (PCC_BITFIELD_TYPE_MATTERS) + DECL_ALIGN (x) = MAX (DECL_ALIGN (x), + TYPE_ALIGN (TREE_TYPE (x))); +#endif + } + } + } + else + /* Non-bit-fields are aligned for their type. */ + DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (TREE_TYPE (x))); + } + else + { + tree type = TREE_TYPE (x); + + while (TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); + + if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x) + && ! TYPE_PTRMEMFUNC_P (type)) + { + /* Never let anything with uninheritable virtuals + make it through without complaint. */ + if (CLASSTYPE_ABSTRACT_VIRTUALS (type)) + abstract_virtuals_error (x, type); + + /* Don't let signatures make it through either. */ + if (IS_SIGNATURE (type)) + signature_error (x, type); + + if (code == UNION_TYPE) + { + const char *fie = NULL; + if (TYPE_NEEDS_CONSTRUCTING (type)) + fie = "constructor"; + else if (TYPE_NEEDS_DESTRUCTOR (type)) + fie = "destructor"; + else if (TYPE_HAS_COMPLEX_ASSIGN_REF (type)) + fie = "copy assignment operator"; + if (fie) + cp_error_at ("member `%#D' with %s not allowed in union", x, + fie); + } + else + { + TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type); + TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type); + TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type); + TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type); + } + + if (!TYPE_HAS_CONST_INIT_REF (type)) + cant_have_const_ctor = 1; + + if (!TYPE_HAS_CONST_ASSIGN_REF (type)) + no_const_asn_ref = 1; + + if (TYPE_HAS_CONSTRUCTOR (type) + && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) + { + cant_have_default_ctor = 1; +#if 0 + /* This is wrong for aggregates. */ + if (! TYPE_HAS_CONSTRUCTOR (t)) + { + if (DECL_NAME (x)) + cp_pedwarn_at ("member `%#D' with only non-default constructor", x); + else + cp_pedwarn_at ("member with only non-default constructor", x); + cp_pedwarn_at ("in class without a constructor", + x); + } +#endif + } + } + if (DECL_INITIAL (x) != NULL_TREE) + { + /* `build_class_init_list' does not recognize + non-FIELD_DECLs. */ + if (code == UNION_TYPE && any_default_members != 0) + cp_error_at ("multiple fields in union `%T' initialized"); + any_default_members = 1; + } + } + } + + /* If this type has any constant members which did not come + with their own initialization, mark that fact here. It is + not an error here, since such types can be saved either by their + constructors, or by fortuitous initialization. */ + CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init; + CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init; + CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals; + CLASSTYPE_HAS_MUTABLE (t) = has_mutable; + + /* Effective C++ rule 11. */ + if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t) + && ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t))) + { + cp_warning ("`%#T' has pointer data members", t); + + if (! TYPE_HAS_INIT_REF (t)) + { + cp_warning (" but does not override `%T(const %T&)'", t, t); + if (! TYPE_HAS_ASSIGN_REF (t)) + cp_warning (" or `operator=(const %T&)'", t); + } + else if (! TYPE_HAS_ASSIGN_REF (t)) + cp_warning (" but does not override `operator=(const %T&)'", t); + } + + /* Do some bookkeeping that will guide the generation of implicitly + declared member functions. */ + TYPE_HAS_COMPLEX_INIT_REF (t) + |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) + || has_virtual || any_default_members); + TYPE_NEEDS_CONSTRUCTING (t) + |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) + || has_virtual || any_default_members); + if (! IS_SIGNATURE (t)) + CLASSTYPE_NON_AGGREGATE (t) + = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t); + TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t); + TYPE_HAS_COMPLEX_ASSIGN_REF (t) + |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); + + /* Synthesize any needed methods. Note that methods will be synthesized + for anonymous unions; grok_x_components undoes that. */ + virtual_dtor + = add_implicitly_declared_members (t, cant_have_default_ctor, + cant_have_const_ctor, + no_const_asn_ref); + if (virtual_dtor) + add_virtual_function (&pending_virtuals, &pending_hard_virtuals, + &has_virtual, virtual_dtor, t); + + if (TYPE_METHODS (t)) + { + finish_struct_methods (t); + method_vec = CLASSTYPE_METHOD_VEC (t); + } + else + { + method_vec = 0; + + /* Just in case these got accidentally + filled in by syntax errors. */ + TYPE_HAS_CONSTRUCTOR (t) = 0; + TYPE_HAS_DESTRUCTOR (t) = 0; + } + + for (access_decls = nreverse (access_decls); access_decls; + access_decls = TREE_CHAIN (access_decls)) + handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields); + + if (vfield == NULL_TREE && has_virtual) + { + /* We build this decl with vtbl_ptr_type_node, which is a + `vtable_entry_type*'. It might seem more precise to use + `vtable_entry_type (*)[N]' where N is the number of firtual + functions. However, that would require the vtable pointer in + base classes to have a different type than the vtable pointer + in derived classes. We could make that happen, but that + still wouldn't solve all the problems. In particular, the + type-based alias analysis code would decide that assignments + to the base class vtable pointer can't alias assignments to + the derived class vtable pointer, since they have different + types. Thus, in an derived class destructor, where the base + class constructor was inlined, we could generate bad code for + setting up the vtable pointer. + + Therefore, we use one type for all vtable pointers. We still + use a type-correct type; it's just doesn't indicate the array + bounds. That's better than using `void*' or some such; it's + cleaner, and it let's the alias analysis code know that these + stores cannot alias stores to void*! */ + vfield = build_lang_field_decl (FIELD_DECL, get_vfield_name (t), + vtbl_ptr_type_node); + /* If you change any of the below, take a look at all the + other VFIELD_BASEs and VTABLE_BASEs in the code, and change + them too. */ + DECL_ASSEMBLER_NAME (vfield) = get_identifier (VFIELD_BASE); + CLASSTYPE_VFIELD (t) = vfield; + DECL_VIRTUAL_P (vfield) = 1; + DECL_ARTIFICIAL (vfield) = 1; + DECL_FIELD_CONTEXT (vfield) = t; + DECL_CLASS_CONTEXT (vfield) = t; + DECL_FCONTEXT (vfield) = t; + DECL_SAVED_INSNS (vfield) = NULL_RTX; + DECL_FIELD_SIZE (vfield) = 0; + DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node); +#if 0 + /* This is more efficient, but breaks binary compatibility, turn + it on sometime when we don't care. If we turn it on, we also + have to enable the code in dfs_init_vbase_pointers. */ + /* vfield is always first entry in structure. */ + TREE_CHAIN (vfield) = fields; + fields = vfield; +#else + if (last_x) + { + my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175); + TREE_CHAIN (last_x) = vfield; + last_x = vfield; + } + else + fields = vfield; +#endif + empty = 0; + vfields = chainon (vfields, build_tree_list (NULL_TREE, t)); + } + + /* Now DECL_INITIAL is null on all members except for zero-width bit-fields. + + C++: maybe we will support default field initialization some day... */ + + /* Delete all duplicate fields from the fields */ + delete_duplicate_fields (fields); + + /* Now we have the nearly final fieldlist for the data fields. Record it, + then lay out the structure or union (including the fields). */ + + TYPE_FIELDS (t) = fields; + + if (n_baseclasses) + { + last_x = build_base_fields (t); + + /* If all our bases are empty, we can be empty too. */ + for (x = last_x; empty && x; x = TREE_CHAIN (x)) + if (DECL_SIZE (x) != integer_zero_node) + empty = 0; + } + + /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus, + we have to save this before we start modifying + TYPE_NONCOPIED_PARTS. */ + inline_friends = CLASSTYPE_INLINE_FRIENDS (t); + CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE; + + if (empty) + { + /* C++: do not let empty structures exist. */ + tree decl = build_lang_field_decl + (FIELD_DECL, NULL_TREE, char_type_node); + TREE_CHAIN (decl) = fields; + TYPE_FIELDS (t) = decl; + TYPE_NONCOPIED_PARTS (t) + = tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t)); + TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1; + } + + if (n_baseclasses) + TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t)); + + layout_type (t); + + /* Remember the size and alignment of the class before adding + the virtual bases. */ + if (empty && flag_new_abi) + CLASSTYPE_SIZE (t) = integer_zero_node; + else if (flag_new_abi && TYPE_HAS_COMPLEX_INIT_REF (t) + && TYPE_HAS_COMPLEX_ASSIGN_REF (t)) + CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t); + else + CLASSTYPE_SIZE (t) = TYPE_SIZE (t); + CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t); + + finish_struct_anon (t); + + /* Set the TYPE_DECL for this type to contain the right + value for DECL_OFFSET, so that we can use it as part + of a COMPONENT_REF for multiple inheritance. */ + + layout_decl (TYPE_MAIN_DECL (t), 0); + + /* Now fix up any virtual base class types that we left lying + around. We must get these done before we try to lay out the + virtual function table. */ + pending_hard_virtuals = nreverse (pending_hard_virtuals); + + if (n_baseclasses) + /* layout_basetypes will remove the base subobject fields. */ + max_has_virtual = layout_basetypes (t, max_has_virtual); + if (empty) + TYPE_FIELDS (t) = fields; + + my_friendly_assert (TYPE_FIELDS (t) == fields, 981117); + + /* Delete all zero-width bit-fields from the front of the fieldlist */ + while (fields && DECL_C_BIT_FIELD (fields) + && DECL_INITIAL (fields)) + fields = TREE_CHAIN (fields); + /* Delete all such fields from the rest of the fields. */ + for (x = fields; x;) + { + if (TREE_CHAIN (x) && DECL_C_BIT_FIELD (TREE_CHAIN (x)) + && DECL_INITIAL (TREE_CHAIN (x))) + TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x)); + else + x = TREE_CHAIN (x); + } + TYPE_FIELDS (t) = fields; + + if (TYPE_USES_VIRTUAL_BASECLASSES (t)) + { + tree vbases; + + vbases = CLASSTYPE_VBASECLASSES (t); + + { + /* Now fixup overrides of all functions in vtables from all + direct or indirect virtual base classes. */ + tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); + int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + for (i = 0; i < n_baseclasses; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree basetype = BINFO_TYPE (base_binfo); + tree vbases; + + vbases = CLASSTYPE_VBASECLASSES (basetype); + while (vbases) + { + merge_overrides (binfo_member (BINFO_TYPE (vbases), + CLASSTYPE_VBASECLASSES (t)), + vbases, 1, t); + vbases = TREE_CHAIN (vbases); + } + } + } + } + + /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we + might need to know it for setting up the offsets in the vtable + (or in thunks) below. */ + if (vfield != NULL_TREE + && DECL_FIELD_CONTEXT (vfield) != t) + { + tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0); + tree offset = BINFO_OFFSET (binfo); + + vfield = copy_node (vfield); + copy_lang_decl (vfield); + + if (! integer_zerop (offset)) + offset = size_binop (MULT_EXPR, offset, size_int (BITS_PER_UNIT)); + DECL_FIELD_CONTEXT (vfield) = t; + DECL_CLASS_CONTEXT (vfield) = t; + DECL_FIELD_BITPOS (vfield) + = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield)); + CLASSTYPE_VFIELD (t) = vfield; + } + +#ifdef NOTQUITE + cp_warning ("Doing hard virtuals for %T...", t); +#endif + + if (has_virtual > max_has_virtual) + max_has_virtual = has_virtual; + if (max_has_virtual > 0) + TYPE_VIRTUAL_P (t) = 1; + + if (flag_rtti && TYPE_VIRTUAL_P (t) && !pending_hard_virtuals) + modify_all_vtables (t, NULL_TREE, NULL_TREE); + + while (pending_hard_virtuals) + { + modify_all_vtables (t, + TREE_PURPOSE (pending_hard_virtuals), + TREE_VALUE (pending_hard_virtuals)); + pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals); + } + + if (TYPE_USES_VIRTUAL_BASECLASSES (t)) + { + tree vbases; + /* Now fixup any virtual function entries from virtual bases + that have different deltas. This has to come after we do the + pending hard virtuals, as we might have a function that comes + from multiple virtual base instances that is only overridden + by a hard virtual above. */ + vbases = CLASSTYPE_VBASECLASSES (t); + while (vbases) + { + /* We might be able to shorten the amount of work we do by + only doing this for vtables that come from virtual bases + that have differing offsets, but don't want to miss any + entries. */ + fixup_vtable_deltas (vbases, 1, t); + vbases = TREE_CHAIN (vbases); + } + } + + /* Under our model of GC, every C++ class gets its own virtual + function table, at least virtually. */ + if (pending_virtuals) + { + pending_virtuals = nreverse (pending_virtuals); + /* We must enter these virtuals into the table. */ + if (first_vfn_base_index < 0) + { + if (! CLASSTYPE_COM_INTERFACE (t)) + { + /* The second slot is for the tdesc pointer when thunks are used. */ + if (flag_vtable_thunks) + pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals); + + /* The first slot is for the rtti offset. */ + pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals); + + set_rtti_entry (pending_virtuals, + convert (ssizetype, integer_zero_node), t); + } + build_vtable (NULL_TREE, t); + } + else + { + /* Here we know enough to change the type of our virtual + function table, but we will wait until later this function. */ + + if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t))) + build_vtable (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index), t); + } + + /* If this type has basetypes with constructors, then those + constructors might clobber the virtual function table. But + they don't if the derived class shares the exact vtable of the base + class. */ + + CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1; + } + else if (first_vfn_base_index >= 0) + { + tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index); + /* This class contributes nothing new to the virtual function + table. However, it may have declared functions which + went into the virtual function table "inherited" from the + base class. If so, we grab a copy of those updated functions, + and pretend they are ours. */ + + /* See if we should steal the virtual info from base class. */ + if (TYPE_BINFO_VTABLE (t) == NULL_TREE) + TYPE_BINFO_VTABLE (t) = BINFO_VTABLE (binfo); + if (TYPE_BINFO_VIRTUALS (t) == NULL_TREE) + TYPE_BINFO_VIRTUALS (t) = BINFO_VIRTUALS (binfo); + if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo)) + CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1; + } + + if (max_has_virtual || first_vfn_base_index >= 0) + { + CLASSTYPE_VSIZE (t) = has_virtual; + if (first_vfn_base_index >= 0) + { + if (pending_virtuals) + TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t), + pending_virtuals); + } + else if (has_virtual) + { + TYPE_BINFO_VIRTUALS (t) = pending_virtuals; + DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)) = 1; + } + } + + /* Now lay out the virtual function table. */ + if (has_virtual) + { + /* Use size_int so values are memoized in common cases. */ + tree itype = build_index_type (size_int (has_virtual)); + tree atype = build_cplus_array_type (vtable_entry_type, itype); + + layout_type (atype); + + CLASSTYPE_VFIELD (t) = vfield; + + /* We may have to grow the vtable. */ + if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype) + { + TREE_TYPE (TYPE_BINFO_VTABLE (t)) = atype; + DECL_SIZE (TYPE_BINFO_VTABLE (t)) = 0; + layout_decl (TYPE_BINFO_VTABLE (t), 0); + /* At one time the vtable info was grabbed 2 words at a time. This + fails on sparc unless you have 8-byte alignment. (tiemann) */ + DECL_ALIGN (TYPE_BINFO_VTABLE (t)) + = MAX (TYPE_ALIGN (double_type_node), + DECL_ALIGN (TYPE_BINFO_VTABLE (t))); + } + } + else if (first_vfn_base_index >= 0) + CLASSTYPE_VFIELD (t) = vfield; + CLASSTYPE_VFIELDS (t) = vfields; + + finish_struct_bits (t, max_has_virtual); + + /* Complete the rtl for any static member objects of the type we're + working on. */ + for (x = fields; x; x = TREE_CHAIN (x)) + { + if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x) + && TREE_TYPE (x) == t) + { + DECL_MODE (x) = TYPE_MODE (t); + make_decl_rtl (x, NULL, 0); + } + } + + if (TYPE_HAS_CONSTRUCTOR (t)) + { + tree vfields = CLASSTYPE_VFIELDS (t); + + while (vfields) + { + /* Mark the fact that constructor for T + could affect anybody inheriting from T + who wants to initialize vtables for VFIELDS's type. */ + if (VF_DERIVED_VALUE (vfields)) + TREE_ADDRESSABLE (vfields) = 1; + vfields = TREE_CHAIN (vfields); + } + } + + /* Write out inline function definitions. */ + do_inline_function_hair (t, inline_friends); + + if (CLASSTYPE_VSIZE (t) != 0) + { +#if 0 + /* This is now done above. */ + if (DECL_FIELD_CONTEXT (vfield) != t) + { + tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0); + tree offset = BINFO_OFFSET (binfo); + + vfield = copy_node (vfield); + copy_lang_decl (vfield); + + if (! integer_zerop (offset)) + offset = size_binop (MULT_EXPR, offset, size_int (BITS_PER_UNIT)); + DECL_FIELD_CONTEXT (vfield) = t; + DECL_CLASS_CONTEXT (vfield) = t; + DECL_FIELD_BITPOS (vfield) + = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield)); + CLASSTYPE_VFIELD (t) = vfield; + } +#endif + + /* In addition to this one, all the other vfields should be listed. */ + /* Before that can be done, we have to have FIELD_DECLs for them, and + a place to find them. */ + TYPE_NONCOPIED_PARTS (t) + = tree_cons (default_conversion (TYPE_BINFO_VTABLE (t)), + vfield, TYPE_NONCOPIED_PARTS (t)); + + if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t) + && DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE) + cp_warning ("`%#T' has virtual functions but non-virtual destructor", + t); + } + + /* Make the rtl for any new vtables we have created, and unmark + the base types we marked. */ + finish_vtbls (TYPE_BINFO (t), 1, t); + /* If we use thunks, and have virtual bases, we might need to emit + additional vtables. */ + if (flag_vtable_thunks && TYPE_USES_PVBASES (t)) + finish_ctor_vtables (t); + hack_incomplete_structures (t); + +#if 0 + if (TYPE_NAME (t) && TYPE_IDENTIFIER (t)) + undo_template_name_overload (TYPE_IDENTIFIER (t), 1); +#endif + + resume_momentary (old); + + if (warn_overloaded_virtual) + warn_hidden (t); + +#if 0 + /* This has to be done after we have sorted out what to do with + the enclosing type. */ + if (write_symbols != DWARF_DEBUG) + { + /* Be smarter about nested classes here. If a type is nested, + only output it if we would output the enclosing type. */ + if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (t))) + DECL_IGNORED_P (TYPE_MAIN_DECL (t)) = TREE_ASM_WRITTEN (TYPE_MAIN_DECL (t)); + } +#endif + + if (write_symbols != DWARF_DEBUG && write_symbols != DWARF2_DEBUG) + { + /* If the type has methods, we want to think about cutting down + the amount of symbol table stuff we output. The value stored in + the TYPE_DECL's DECL_IGNORED_P slot is a first approximation. + For example, if a member function is seen and we decide to + write out that member function, then we can change the value + of the DECL_IGNORED_P slot, and the type will be output when + that member function's debug info is written out. + + We can't do this with DWARF, which does not support name + references between translation units. */ + if (CLASSTYPE_METHOD_VEC (t)) + { + /* Don't output full info about any type + which does not have its implementation defined here. */ + if (CLASSTYPE_INTERFACE_ONLY (t)) + TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1; +#if 0 + /* XXX do something about this. */ + else if (CLASSTYPE_INTERFACE_UNKNOWN (t)) + /* Only a first approximation! */ + TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1; +#endif + } + else if (CLASSTYPE_INTERFACE_ONLY (t)) + TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1; + } + + /* Finish debugging output for this type. */ + rest_of_type_compilation (t, toplevel_bindings_p ()); + + return; +} + +/* When T was built up, the member declarations were added in reverse + order. Rearrange them to declaration order. */ + +void +unreverse_member_declarations (t) + tree t; +{ + tree next; + tree prev; + tree x; + + /* The TYPE_FIELDS, TYPE_METHODS, and CLASSTYPE_TAGS are all in + reverse order. Put them in declaration order now. */ + TYPE_METHODS (t) = nreverse (TYPE_METHODS (t)); + CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (t)); + + /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in + reverse order, so we can't just use nreverse. */ + prev = NULL_TREE; + for (x = TYPE_FIELDS (t); + x && TREE_CODE (x) != TYPE_DECL; + x = next) + { + next = TREE_CHAIN (x); + TREE_CHAIN (x) = prev; + prev = x; + } + if (prev) + { + TREE_CHAIN (TYPE_FIELDS (t)) = x; + if (prev) + TYPE_FIELDS (t) = prev; + } +} + +tree +finish_struct (t, attributes, warn_anon) + tree t, attributes; + int warn_anon; +{ + tree name = TYPE_NAME (t); + + if (TREE_CODE (name) == TYPE_DECL) + { + extern int lineno; + + DECL_SOURCE_FILE (name) = input_filename; + /* For TYPE_DECL that are not typedefs (those marked with a line + number of zero, we don't want to mark them as real typedefs. + If this fails one needs to make sure real typedefs have a + previous line number, even if it is wrong, that way the below + will fill in the right line number. (mrs) */ + if (DECL_SOURCE_LINE (name)) + DECL_SOURCE_LINE (name) = lineno; + name = DECL_NAME (name); + } + + /* Append the fields we need for constructing signature tables. */ + if (IS_SIGNATURE (t)) + append_signature_fields (t); + + /* Now that we've got all the field declarations, reverse everything + as necessary. */ + unreverse_member_declarations (t); + + cplus_decl_attributes (t, attributes, NULL_TREE); + + if (processing_template_decl) + { + tree d = getdecls (); + for (; d; d = TREE_CHAIN (d)) + { + /* If this is the decl for the class or one of the template + parms, we've seen all the injected decls. */ + if ((TREE_CODE (d) == TYPE_DECL + && (TREE_TYPE (d) == t + || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TYPE_PARM + || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TEMPLATE_PARM)) + || TREE_CODE (d) == CONST_DECL) + break; + /* Don't inject cache decls. */ + else if (IDENTIFIER_TEMPLATE (DECL_NAME (d))) + continue; + DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t)) + = tree_cons (NULL_TREE, d, + DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t))); + } + finish_struct_methods (t); + TYPE_SIZE (t) = integer_zero_node; + } + else + finish_struct_1 (t, warn_anon); + + TYPE_BEING_DEFINED (t) = 0; + + if (current_class_type) + popclass (); + else + error ("trying to finish struct, but kicked out due to previous parse errors."); + + return t; +} + +/* Return the dynamic type of INSTANCE, if known. + Used to determine whether the virtual function table is needed + or not. + + *NONNULL is set iff INSTANCE can be known to be nonnull, regardless + of our knowledge of its type. */ + +static tree +fixed_type_or_null (instance, nonnull) + tree instance; + int *nonnull; +{ + switch (TREE_CODE (instance)) + { + case INDIRECT_REF: + /* Check that we are not going through a cast of some sort. */ + if (TREE_TYPE (instance) + == TREE_TYPE (TREE_TYPE (TREE_OPERAND (instance, 0)))) + instance = TREE_OPERAND (instance, 0); + /* fall through... */ + case CALL_EXPR: + /* This is a call to a constructor, hence it's never zero. */ + if (TREE_HAS_CONSTRUCTOR (instance)) + { + if (nonnull) + *nonnull = 1; + return TREE_TYPE (instance); + } + return NULL_TREE; + + case SAVE_EXPR: + /* This is a call to a constructor, hence it's never zero. */ + if (TREE_HAS_CONSTRUCTOR (instance)) + { + if (nonnull) + *nonnull = 1; + return TREE_TYPE (instance); + } + return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull); + + case RTL_EXPR: + return NULL_TREE; + + case PLUS_EXPR: + case MINUS_EXPR: + if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST) + /* Propagate nonnull. */ + fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull); + if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR) + return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull); + return NULL_TREE; + + case NOP_EXPR: + case CONVERT_EXPR: + return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull); + + case ADDR_EXPR: + if (nonnull) + *nonnull = 1; + return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull); + + case COMPONENT_REF: + return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull); + + case VAR_DECL: + case FIELD_DECL: + if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE + && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (instance)))) + { + if (nonnull) + *nonnull = 1; + return TREE_TYPE (TREE_TYPE (instance)); + } + /* fall through... */ + case TARGET_EXPR: + case PARM_DECL: + if (IS_AGGR_TYPE (TREE_TYPE (instance))) + { + if (nonnull) + *nonnull = 1; + return TREE_TYPE (instance); + } + else if (nonnull) + { + if (instance == current_class_ptr + && flag_this_is_variable <= 0) + { + /* Normally, 'this' must be non-null. */ + if (flag_this_is_variable == 0) + *nonnull = 1; + + /* <0 means we're in a constructor and we know our type. */ + if (flag_this_is_variable < 0) + return TREE_TYPE (TREE_TYPE (instance)); + } + else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) + /* Reference variables should be references to objects. */ + *nonnull = 1; + } + return NULL_TREE; + + default: + return NULL_TREE; + } +} + +/* Return non-zero if the dynamic type of INSTANCE is known, and equivalent + to the static type. We also handle the case where INSTANCE is really + a pointer. + + Used to determine whether the virtual function table is needed + or not. + + *NONNULL is set iff INSTANCE can be known to be nonnull, regardless + of our knowledge of its type. */ + +int +resolves_to_fixed_type_p (instance, nonnull) + tree instance; + int *nonnull; +{ + tree t = TREE_TYPE (instance); + tree fixed = fixed_type_or_null (instance, nonnull); + if (fixed == NULL_TREE) + return 0; + if (POINTER_TYPE_P (t)) + t = TREE_TYPE (t); + return same_type_p (TYPE_MAIN_VARIANT (t), TYPE_MAIN_VARIANT (fixed)); +} + + +void +init_class_processing () +{ + current_class_depth = 0; + current_class_stack_size = 10; + current_class_stack + = (class_stack_node_t) xmalloc (current_class_stack_size + * sizeof (struct class_stack_node)); + + current_lang_stacksize = 10; + current_lang_base = (tree *)xmalloc(current_lang_stacksize * sizeof (tree)); + current_lang_stack = current_lang_base; + + access_default_node = build_int_2 (0, 0); + access_public_node = build_int_2 (1, 0); + access_protected_node = build_int_2 (2, 0); + access_private_node = build_int_2 (3, 0); + access_default_virtual_node = build_int_2 (4, 0); + access_public_virtual_node = build_int_2 (5, 0); + access_protected_virtual_node = build_int_2 (6, 0); + access_private_virtual_node = build_int_2 (7, 0); + + /* Keep these values lying around. */ + base_layout_decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, error_mark_node); + TREE_TYPE (base_layout_decl) = make_node (RECORD_TYPE); + + gcc_obstack_init (&class_obstack); +} + +/* Set current scope to NAME. CODE tells us if this is a + STRUCT, UNION, or ENUM environment. + + NAME may end up being NULL_TREE if this is an anonymous or + late-bound struct (as in "struct { ... } foo;") */ + +/* Set global variables CURRENT_CLASS_NAME and CURRENT_CLASS_TYPE to + appropriate values, found by looking up the type definition of + NAME (as a CODE). + + If MODIFY is 1, we set IDENTIFIER_CLASS_VALUE's of names + which can be seen locally to the class. They are shadowed by + any subsequent local declaration (including parameter names). + + If MODIFY is 2, we set IDENTIFIER_CLASS_VALUE's of names + which have static meaning (i.e., static members, static + member functions, enum declarations, etc). + + If MODIFY is 3, we set IDENTIFIER_CLASS_VALUE of names + which can be seen locally to the class (as in 1), but + know that we are doing this for declaration purposes + (i.e. friend foo::bar (int)). + + So that we may avoid calls to lookup_name, we cache the _TYPE + nodes of local TYPE_DECLs in the TREE_TYPE field of the name. + + For multiple inheritance, we perform a two-pass depth-first search + of the type lattice. The first pass performs a pre-order search, + marking types after the type has had its fields installed in + the appropriate IDENTIFIER_CLASS_VALUE slot. The second pass merely + unmarks the marked types. If a field or member function name + appears in an ambiguous way, the IDENTIFIER_CLASS_VALUE of + that name becomes `error_mark_node'. */ + +void +pushclass (type, modify) + tree type; + int modify; +{ + type = TYPE_MAIN_VARIANT (type); + + /* Make sure there is enough room for the new entry on the stack. */ + if (current_class_depth + 1 >= current_class_stack_size) + { + current_class_stack_size *= 2; + current_class_stack + = (class_stack_node_t) xrealloc (current_class_stack, + current_class_stack_size + * sizeof (struct class_stack_node)); + } + + /* Insert a new entry on the class stack. */ + current_class_stack[current_class_depth].name = current_class_name; + current_class_stack[current_class_depth].type = current_class_type; + current_class_stack[current_class_depth].access = current_access_specifier; + current_class_stack[current_class_depth].names_used = 0; + current_class_depth++; + + /* Now set up the new type. */ + current_class_name = TYPE_NAME (type); + if (TREE_CODE (current_class_name) == TYPE_DECL) + current_class_name = DECL_NAME (current_class_name); + current_class_type = type; + + /* By default, things in classes are private, while things in + structures or unions are public. */ + current_access_specifier = (CLASSTYPE_DECLARED_CLASS (type) + ? access_private_node + : access_public_node); + + if (previous_class_type != NULL_TREE + && (type != previous_class_type + || TYPE_SIZE (previous_class_type) == NULL_TREE) + && current_class_depth == 1) + { + /* Forcibly remove any old class remnants. */ + invalidate_class_lookup_cache (); + + /* Now, free the obstack on which we cached all the values. */ + if (class_cache_firstobj) + obstack_free (&class_cache_obstack, class_cache_firstobj); + class_cache_firstobj + = (char*) obstack_finish (&class_cache_obstack); + } + + /* If we're about to enter a nested class, clear + IDENTIFIER_CLASS_VALUE for the enclosing classes. */ + if (modify && current_class_depth > 1) + clear_identifier_class_values (); + + pushlevel_class (); + +#if 0 + if (CLASSTYPE_TEMPLATE_INFO (type)) + overload_template_name (type); +#endif + + if (modify) + { + if (type != previous_class_type || current_class_depth > 1) + push_class_decls (type); + else + { + tree item; + + /* We are re-entering the same class we just left, so we + don't have to search the whole inheritance matrix to find + all the decls to bind again. Instead, we install the + cached class_shadowed list, and walk through it binding + names and setting up IDENTIFIER_TYPE_VALUEs. */ + set_class_shadows (previous_class_values); + for (item = previous_class_values; item; item = TREE_CHAIN (item)) + { + tree id = TREE_PURPOSE (item); + tree decl = TREE_TYPE (item); + + push_class_binding (id, decl); + if (TREE_CODE (decl) == TYPE_DECL) + set_identifier_type_value (id, TREE_TYPE (decl)); + } + unuse_fields (type); + } + + storetags (CLASSTYPE_TAGS (type)); + } +} + +/* When we exit a toplevel class scope, we save the + IDENTIFIER_CLASS_VALUEs so that we can restore them quickly if we + reenter the class. Here, we've entered some other class, so we + must invalidate our cache. */ + +void +invalidate_class_lookup_cache () +{ + tree t; + + /* This code can be seen as a cache miss. When we've cached a + class' scope's bindings and we can't use them, we need to reset + them. This is it! */ + for (t = previous_class_values; t; t = TREE_CHAIN (t)) + IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE; + + previous_class_type = NULL_TREE; +} + +/* Get out of the current class scope. If we were in a class scope + previously, that is the one popped to. */ + +void +popclass () +{ + poplevel (1, 0, 0); + /* Since poplevel_class does the popping of class decls nowadays, + this really only frees the obstack used for these decls. */ + pop_class_decls (); + + current_class_depth--; + current_class_name = current_class_stack[current_class_depth].name; + current_class_type = current_class_stack[current_class_depth].type; + current_access_specifier = current_class_stack[current_class_depth].access; + if (current_class_stack[current_class_depth].names_used) + splay_tree_delete (current_class_stack[current_class_depth].names_used); +} + +/* Returns 1 if current_class_type is either T or a nested type of T. */ + +int +currently_open_class (t) + tree t; +{ + int i; + if (t == current_class_type) + return 1; + for (i = 0; i < current_class_depth; ++i) + if (current_class_stack [i].type == t) + return 1; + return 0; +} + +/* When entering a class scope, all enclosing class scopes' names with + static meaning (static variables, static functions, types and enumerators) + have to be visible. This recursive function calls pushclass for all + enclosing class contexts until global or a local scope is reached. + TYPE is the enclosed class and MODIFY is equivalent with the pushclass + formal of the same name. */ + +void +push_nested_class (type, modify) + tree type; + int modify; +{ + tree context; + + /* A namespace might be passed in error cases, like A::B:C. */ + if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type) + || TREE_CODE (type) == NAMESPACE_DECL + || TREE_CODE (type) == TEMPLATE_TYPE_PARM + || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM) + return; + + context = DECL_CONTEXT (TYPE_MAIN_DECL (type)); + + if (context && CLASS_TYPE_P (context)) + push_nested_class (context, 2); + pushclass (type, modify); +} + +/* Undoes a push_nested_class call. MODIFY is passed on to popclass. */ + +void +pop_nested_class () +{ + tree context = DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type)); + + popclass (); + if (context && CLASS_TYPE_P (context)) + pop_nested_class (); +} + +/* Set global variables CURRENT_LANG_NAME to appropriate value + so that behavior of name-mangling machinery is correct. */ + +void +push_lang_context (name) + tree name; +{ + *current_lang_stack++ = current_lang_name; + if (current_lang_stack >= current_lang_base + current_lang_stacksize) + { + current_lang_base + = (tree *)xrealloc (current_lang_base, + sizeof (tree) * (current_lang_stacksize + 10)); + current_lang_stack = current_lang_base + current_lang_stacksize; + current_lang_stacksize += 10; + } + + if (name == lang_name_cplusplus) + { + strict_prototype = strict_prototypes_lang_cplusplus; + current_lang_name = name; + } + else if (name == lang_name_java) + { + strict_prototype = strict_prototypes_lang_cplusplus; + current_lang_name = name; + /* DECL_IGNORED_P is initially set for these types, to avoid clutter. + (See record_builtin_java_type in decl.c.) However, that causes + incorrect debug entries if these types are actually used. + So we re-enable debug output after extern "Java". */ + DECL_IGNORED_P (java_byte_type_node) = 0; + DECL_IGNORED_P (java_short_type_node) = 0; + DECL_IGNORED_P (java_int_type_node) = 0; + DECL_IGNORED_P (java_long_type_node) = 0; + DECL_IGNORED_P (java_float_type_node) = 0; + DECL_IGNORED_P (java_double_type_node) = 0; + DECL_IGNORED_P (java_char_type_node) = 0; + DECL_IGNORED_P (java_boolean_type_node) = 0; + } + else if (name == lang_name_c) + { + strict_prototype = strict_prototypes_lang_c; + current_lang_name = name; + } + else + error ("language string `\"%s\"' not recognized", IDENTIFIER_POINTER (name)); +} + +/* Get out of the current language scope. */ + +void +pop_lang_context () +{ + current_lang_name = *--current_lang_stack; + if (current_lang_name == lang_name_cplusplus + || current_lang_name == lang_name_java) + strict_prototype = strict_prototypes_lang_cplusplus; + else if (current_lang_name == lang_name_c) + strict_prototype = strict_prototypes_lang_c; +} + +/* Type instantiation routines. */ + +/* Given an OVERLOAD and a TARGET_TYPE, return the function that + matches the TARGET_TYPE. If there is no satisfactory match, return + error_mark_node, and issue an error message if COMPLAIN is + non-zero. If TEMPLATE_ONLY, the name of the overloaded function + was a template-id, and EXPLICIT_TARGS are the explicitly provided + template arguments. */ + +static tree +resolve_address_of_overloaded_function (target_type, + overload, + complain, + template_only, + explicit_targs) + tree target_type; + tree overload; + int complain; + int template_only; + tree explicit_targs; +{ + /* Here's what the standard says: + + [over.over] + + If the name is a function template, template argument deduction + is done, and if the argument deduction succeeds, the deduced + arguments are used to generate a single template function, which + is added to the set of overloaded functions considered. + + Non-member functions and static member functions match targets of + type "pointer-to-function" or "reference-to-function." Nonstatic + member functions match targets of type "pointer-to-member + function;" the function type of the pointer to member is used to + select the member function from the set of overloaded member + functions. If a nonstatic member function is selected, the + reference to the overloaded function name is required to have the + form of a pointer to member as described in 5.3.1. + + If more than one function is selected, any template functions in + the set are eliminated if the set also contains a non-template + function, and any given template function is eliminated if the + set contains a second template function that is more specialized + than the first according to the partial ordering rules 14.5.5.2. + After such eliminations, if any, there shall remain exactly one + selected function. */ + + int is_ptrmem = 0; + int is_reference = 0; + /* We store the matches in a TREE_LIST rooted here. The functions + are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy + interoperability with most_specialized_instantiation. */ + tree matches = NULL_TREE; + tree fn; + + /* By the time we get here, we should be seeing only real + pointer-to-member types, not the internal POINTER_TYPE to + METHOD_TYPE representation. */ + my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (target_type)) + == METHOD_TYPE)), 0); + + /* Check that the TARGET_TYPE is reasonable. */ + if (TYPE_PTRFN_P (target_type)) + /* This is OK. */ + ; + else if (TYPE_PTRMEMFUNC_P (target_type)) + /* This is OK, too. */ + is_ptrmem = 1; + else if (TREE_CODE (target_type) == FUNCTION_TYPE) + { + /* This is OK, too. This comes from a conversion to reference + type. */ + target_type = build_reference_type (target_type); + is_reference = 1; + } + else + { + if (complain) + cp_error("cannot resolve overloaded function `%D' based on conversion to type `%T'", + DECL_NAME (OVL_FUNCTION (overload)), target_type); + return error_mark_node; + } + + /* If we can find a non-template function that matches, we can just + use it. There's no point in generating template instantiations + if we're just going to throw them out anyhow. But, of course, we + can only do this when we don't *need* a template function. */ + if (!template_only) + { + tree fns; + + for (fns = overload; fns; fns = OVL_CHAIN (fns)) + { + tree fn = OVL_FUNCTION (fns); + tree fntype; + + if (TREE_CODE (fn) == TEMPLATE_DECL) + /* We're not looking for templates just yet. */ + continue; + + if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) + != is_ptrmem) + /* We're looking for a non-static member, and this isn't + one, or vice versa. */ + continue; + + /* See if there's a match. */ + fntype = TREE_TYPE (fn); + if (is_ptrmem) + fntype = build_ptrmemfunc_type (build_pointer_type (fntype)); + else if (!is_reference) + fntype = build_pointer_type (fntype); + + if (can_convert_arg (target_type, fntype, fn)) + matches = scratch_tree_cons (fn, NULL_TREE, matches); + } + } + + /* Now, if we've already got a match (or matches), there's no need + to proceed to the template functions. But, if we don't have a + match we need to look at them, too. */ + if (!matches) + { + tree target_fn_type; + tree target_arg_types; + tree fns; + + if (is_ptrmem) + target_fn_type + = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (target_type)); + else + target_fn_type = TREE_TYPE (target_type); + target_arg_types = TYPE_ARG_TYPES (target_fn_type); + + for (fns = overload; fns; fns = OVL_CHAIN (fns)) + { + tree fn = OVL_FUNCTION (fns); + tree instantiation; + tree instantiation_type; + tree targs; + + if (TREE_CODE (fn) != TEMPLATE_DECL) + /* We're only looking for templates. */ + continue; + + if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) + != is_ptrmem) + /* We're not looking for a non-static member, and this is + one, or vice versa. */ + continue; + + /* Try to do argument deduction. */ + targs = make_scratch_vec (DECL_NTPARMS (fn)); + if (fn_type_unification (fn, explicit_targs, targs, + target_arg_types, NULL_TREE, + DEDUCE_EXACT) != 0) + /* Argument deduction failed. */ + continue; + + /* Instantiate the template. */ + instantiation = instantiate_template (fn, targs); + if (instantiation == error_mark_node) + /* Instantiation failed. */ + continue; + + /* See if there's a match. */ + instantiation_type = TREE_TYPE (instantiation); + if (is_ptrmem) + instantiation_type = + build_ptrmemfunc_type (build_pointer_type (instantiation_type)); + else if (!is_reference) + instantiation_type = build_pointer_type (instantiation_type); + if (can_convert_arg (target_type, instantiation_type, instantiation)) + matches = scratch_tree_cons (instantiation, fn, matches); + } + + /* Now, remove all but the most specialized of the matches. */ + if (matches) + { + tree match = most_specialized_instantiation (matches, + explicit_targs); + + if (match != error_mark_node) + matches = scratch_tree_cons (match, NULL_TREE, NULL_TREE); + } + } + + /* Now we should have exactly one function in MATCHES. */ + if (matches == NULL_TREE) + { + /* There were *no* matches. */ + if (complain) + { + cp_error ("no matches converting function `%D' to type `%#T'", + DECL_NAME (OVL_FUNCTION (overload)), + target_type); + + /* print_candidates expects a chain with the functions in + TREE_VALUE slots, so we cons one up here (we're losing anyway, + so why be clever?). */ + for (; overload; overload = OVL_NEXT (overload)) + matches = scratch_tree_cons (NULL_TREE, OVL_CURRENT (overload), + matches); + + print_candidates (matches); + } + return error_mark_node; + } + else if (TREE_CHAIN (matches)) + { + /* There were too many matches. */ + + if (complain) + { + tree match; + + cp_error ("converting overloaded function `%D' to type `%#T' is ambiguous", + DECL_NAME (OVL_FUNCTION (overload)), + target_type); + + /* Since print_candidates expects the functions in the + TREE_VALUE slot, we flip them here. */ + for (match = matches; match; match = TREE_CHAIN (match)) + TREE_VALUE (match) = TREE_PURPOSE (match); + + print_candidates (matches); + } + + return error_mark_node; + } + + /* Good, exactly one match. Now, convert it to the correct type. */ + fn = TREE_PURPOSE (matches); + + mark_used (fn); + + if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type)) + return build_unary_op (ADDR_EXPR, fn, 0); + else + { + /* The target must be a REFERENCE_TYPE. Above, build_unary_op + will mark the function as addressed, but here we must do it + explicitly. */ + mark_addressable (fn); + + return fn; + } +} + +/* This function will instantiate the type of the expression given in + RHS to match the type of LHSTYPE. If errors exist, then return + error_mark_node. We only complain is COMPLAIN is set. If we are + not complaining, never modify rhs, as overload resolution wants to + try many possible instantiations, in hopes that at least one will + work. + + FLAGS is a bitmask, as we see at the top of the function. + + For non-recursive calls, LHSTYPE should be a function, pointer to + function, or a pointer to member function. */ + +tree +instantiate_type (lhstype, rhs, flags) + tree lhstype, rhs; + int flags; +{ + int complain = (flags & 1); + int strict = (flags & 2) ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT; + + if (TREE_CODE (lhstype) == UNKNOWN_TYPE) + { + if (complain) + error ("not enough type information"); + return error_mark_node; + } + + if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs))) + { + if (comptypes (lhstype, TREE_TYPE (rhs), strict)) + return rhs; + if (complain) + cp_error ("argument of type `%T' does not match `%T'", + TREE_TYPE (rhs), lhstype); + return error_mark_node; + } + + /* We don't overwrite rhs if it is an overloaded function. + Copying it would destroy the tree link. */ + if (TREE_CODE (rhs) != OVERLOAD) + rhs = copy_node (rhs); + + /* This should really only be used when attempting to distinguish + what sort of a pointer to function we have. For now, any + arithmetic operation which is not supported on pointers + is rejected as an error. */ + + switch (TREE_CODE (rhs)) + { + case TYPE_EXPR: + case CONVERT_EXPR: + case SAVE_EXPR: + case CONSTRUCTOR: + case BUFFER_REF: + my_friendly_abort (177); + return error_mark_node; + + case INDIRECT_REF: + case ARRAY_REF: + { + tree new_rhs; + + new_rhs = instantiate_type (build_pointer_type (lhstype), + TREE_OPERAND (rhs, 0), flags); + if (new_rhs == error_mark_node) + return error_mark_node; + + TREE_TYPE (rhs) = lhstype; + TREE_OPERAND (rhs, 0) = new_rhs; + return rhs; + } + + case NOP_EXPR: + rhs = copy_node (TREE_OPERAND (rhs, 0)); + TREE_TYPE (rhs) = unknown_type_node; + return instantiate_type (lhstype, rhs, flags); + + case COMPONENT_REF: + { + tree field = TREE_OPERAND (rhs, 1); + tree r; + + r = instantiate_type (lhstype, field, flags); + + if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype)) + { + if (complain) + { + tree t = TYPE_PTRMEMFUNC_OBJECT_TYPE (lhstype); + + if (TREE_CODE (field) == OVERLOAD) + field = OVL_FUNCTION (field); + if (TREE_CODE (field) == FUNCTION_DECL) + { + cp_pedwarn ("object-dependent reference `%E' can only be used in a call", + DECL_NAME (field)); + cp_pedwarn (" to form a pointer to member function, say `&%T::%E'", + t, DECL_NAME (field)); + } + else + cp_pedwarn ("object-dependent reference can only be used in a call"); + } + return r; + } + + return r; + } + + case OFFSET_REF: + rhs = TREE_OPERAND (rhs, 1); + if (BASELINK_P (rhs)) + return instantiate_type (lhstype, TREE_VALUE (rhs), flags); + + /* This can happen if we are forming a pointer-to-member for a + member template. */ + my_friendly_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR, 0); + + /* Fall through. */ + + case TEMPLATE_ID_EXPR: + return + resolve_address_of_overloaded_function (lhstype, + TREE_OPERAND (rhs, 0), + complain, + /*template_only=*/1, + TREE_OPERAND (rhs, 1)); + + case OVERLOAD: + return + resolve_address_of_overloaded_function (lhstype, + rhs, + complain, + /*template_only=*/0, + /*explicit_targs=*/NULL_TREE); + + case TREE_LIST: + /* Now we should have a baselink. */ + my_friendly_assert (BASELINK_P (rhs), 990412); + + return instantiate_type (lhstype, TREE_VALUE (rhs), flags); + + case CALL_EXPR: + /* This is too hard for now. */ + my_friendly_abort (183); + return error_mark_node; + + case PLUS_EXPR: + case MINUS_EXPR: + case COMPOUND_EXPR: + TREE_OPERAND (rhs, 0) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags); + if (TREE_OPERAND (rhs, 0) == error_mark_node) + return error_mark_node; + TREE_OPERAND (rhs, 1) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags); + if (TREE_OPERAND (rhs, 1) == error_mark_node) + return error_mark_node; + + TREE_TYPE (rhs) = lhstype; + return rhs; + + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case FLOOR_DIV_EXPR: + case CEIL_DIV_EXPR: + case ROUND_DIV_EXPR: + case RDIV_EXPR: + case TRUNC_MOD_EXPR: + case FLOOR_MOD_EXPR: + case CEIL_MOD_EXPR: + case ROUND_MOD_EXPR: + case FIX_ROUND_EXPR: + case FIX_FLOOR_EXPR: + case FIX_CEIL_EXPR: + case FIX_TRUNC_EXPR: + case FLOAT_EXPR: + case NEGATE_EXPR: + case ABS_EXPR: + case MAX_EXPR: + case MIN_EXPR: + case FFS_EXPR: + + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case LROTATE_EXPR: + case RROTATE_EXPR: + + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + if (complain) + error ("invalid operation on uninstantiated type"); + return error_mark_node; + + case TRUTH_AND_EXPR: + case TRUTH_OR_EXPR: + case TRUTH_XOR_EXPR: + case LT_EXPR: + case LE_EXPR: + case GT_EXPR: + case GE_EXPR: + case EQ_EXPR: + case NE_EXPR: + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + case TRUTH_NOT_EXPR: + if (complain) + error ("not enough type information"); + return error_mark_node; + + case COND_EXPR: + if (type_unknown_p (TREE_OPERAND (rhs, 0))) + { + if (complain) + error ("not enough type information"); + return error_mark_node; + } + TREE_OPERAND (rhs, 1) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags); + if (TREE_OPERAND (rhs, 1) == error_mark_node) + return error_mark_node; + TREE_OPERAND (rhs, 2) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), flags); + if (TREE_OPERAND (rhs, 2) == error_mark_node) + return error_mark_node; + + TREE_TYPE (rhs) = lhstype; + return rhs; + + case MODIFY_EXPR: + TREE_OPERAND (rhs, 1) + = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags); + if (TREE_OPERAND (rhs, 1) == error_mark_node) + return error_mark_node; + + TREE_TYPE (rhs) = lhstype; + return rhs; + + case ADDR_EXPR: + return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags); + + case ENTRY_VALUE_EXPR: + my_friendly_abort (184); + return error_mark_node; + + case ERROR_MARK: + return error_mark_node; + + default: + my_friendly_abort (185); + return error_mark_node; + } +} + +/* Return the name of the virtual function pointer field + (as an IDENTIFIER_NODE) for the given TYPE. Note that + this may have to look back through base types to find the + ultimate field name. (For single inheritance, these could + all be the same name. Who knows for multiple inheritance). */ + +static tree +get_vfield_name (type) + tree type; +{ + tree binfo = TYPE_BINFO (type); + char *buf; + + while (BINFO_BASETYPES (binfo) + && TYPE_VIRTUAL_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0))) + && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0))) + binfo = BINFO_BASETYPE (binfo, 0); + + type = BINFO_TYPE (binfo); + buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT) + + TYPE_NAME_LENGTH (type) + 2); + sprintf (buf, VFIELD_NAME_FORMAT, TYPE_NAME_STRING (type)); + return get_identifier (buf); +} + +void +print_class_statistics () +{ +#ifdef GATHER_STATISTICS + fprintf (stderr, "convert_harshness = %d\n", n_convert_harshness); + fprintf (stderr, "compute_conversion_costs = %d\n", n_compute_conversion_costs); + fprintf (stderr, "build_method_call = %d (inner = %d)\n", + n_build_method_call, n_inner_fields_searched); + if (n_vtables) + { + fprintf (stderr, "vtables = %d; vtable searches = %d\n", + n_vtables, n_vtable_searches); + fprintf (stderr, "vtable entries = %d; vtable elems = %d\n", + n_vtable_entries, n_vtable_elems); + } +#endif +} + +/* Push an obstack which is sufficiently long-lived to hold such class + decls that may be cached in the previous_class_values list. The + effect is undone by pop_obstacks. */ + +void +push_cache_obstack () +{ + static int cache_obstack_initialized; + + if (!cache_obstack_initialized) + { + gcc_obstack_init (&class_cache_obstack); + class_cache_firstobj + = (char*) obstack_finish (&class_cache_obstack); + cache_obstack_initialized = 1; + } + + push_obstacks_nochange (); + current_obstack = &class_cache_obstack; +} + +/* Build a dummy reference to ourselves so Derived::Base (and A::A) works, + according to [class]: + The class-name is also inserted + into the scope of the class itself. For purposes of access checking, + the inserted class name is treated as if it were a public member name. */ + +void +build_self_reference () +{ + tree name = constructor_name (current_class_type); + tree value = build_lang_decl (TYPE_DECL, name, current_class_type); + tree saved_cas; + + DECL_NONLOCAL (value) = 1; + DECL_CONTEXT (value) = current_class_type; + DECL_CLASS_CONTEXT (value) = current_class_type; + DECL_ARTIFICIAL (value) = 1; + + saved_cas = current_access_specifier; + current_access_specifier = access_public_node; + finish_member_declaration (value); + current_access_specifier = saved_cas; +} + +/* Returns 1 if TYPE contains only padding bytes. */ + +int +is_empty_class (type) + tree type; +{ + tree t; + + if (type == error_mark_node) + return 0; + + if (! IS_AGGR_TYPE (type)) + return 0; + + if (flag_new_abi) + return CLASSTYPE_SIZE (type) == integer_zero_node; + + if (TYPE_BINFO_BASETYPES (type)) + return 0; + t = TYPE_FIELDS (type); + while (t && TREE_CODE (t) != FIELD_DECL) + t = TREE_CHAIN (t); + return (t == NULL_TREE); +} + +/* Find the enclosing class of the given NODE. NODE can be a *_DECL or + a *_TYPE node. NODE can also be a local class. */ + +tree +get_enclosing_class (type) + tree type; +{ + tree node = type; + + while (node && TREE_CODE (node) != NAMESPACE_DECL) + { + switch (TREE_CODE_CLASS (TREE_CODE (node))) + { + case 'd': + node = DECL_CONTEXT (node); + break; + + case 't': + if (node != type) + return node; + node = TYPE_CONTEXT (node); + break; + + default: + my_friendly_abort (0); + } + } + return NULL_TREE; +} + +/* Return 1 if TYPE or one of its enclosing classes is derived from BASE. */ + +int +is_base_of_enclosing_class (base, type) + tree base, type; +{ + while (type) + { + if (get_binfo (base, type, 0)) + return 1; + + type = get_enclosing_class (type); + } + return 0; +} + +/* Note that NAME was looked up while the current class was being + defined and that the result of that lookup was DECL. */ + +void +maybe_note_name_used_in_class (name, decl) + tree name; + tree decl; +{ + splay_tree names_used; + + /* If we're not defining a class, there's nothing to do. */ + if (!current_class_type || !TYPE_BEING_DEFINED (current_class_type)) + return; + + /* If there's already a binding for this NAME, then we don't have + anything to worry about. */ + if (IDENTIFIER_CLASS_VALUE (name)) + return; + + if (!current_class_stack[current_class_depth - 1].names_used) + current_class_stack[current_class_depth - 1].names_used + = splay_tree_new (splay_tree_compare_pointers, 0, 0); + names_used = current_class_stack[current_class_depth - 1].names_used; + + splay_tree_insert (names_used, + (splay_tree_key) name, + (splay_tree_value) decl); +} + +/* Note that NAME was declared (as DECL) in the current class. Check + to see that the declaration is legal. */ + +void +note_name_declared_in_class (name, decl) + tree name; + tree decl; +{ + splay_tree names_used; + splay_tree_node n; + + /* Look to see if we ever used this name. */ + names_used + = current_class_stack[current_class_depth - 1].names_used; + if (!names_used) + return; + + n = splay_tree_lookup (names_used, (splay_tree_key) name); + if (n) + { + /* [basic.scope.class] + + A name N used in a class S shall refer to the same declaration + in its context and when re-evaluated in the completed scope of + S. */ + cp_error ("declaration of `%#D'", decl); + cp_error_at ("changes meaning of `%s' from `%+#D'", + IDENTIFIER_POINTER (DECL_NAME (decl)), + (tree) n->value); + } +} Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/class.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/cp-tree.h =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/cp-tree.h (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/cp-tree.h (revision 60969) @@ -0,0 +1,3574 @@ +/* Definitions for C++ parsing and type checking. + Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc. + Hacked by Michael Tiemann (tiemann@cygnus.com) + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifndef _CP_TREE_H +#define _CP_TREE_H + +/* Usage of TREE_LANG_FLAG_?: + 0: BINFO_MARKED (BINFO nodes). + COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT). + NEW_EXPR_USE_GLOBAL (in NEW_EXPR). + DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR). + LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR). + TREE_NEGATED_INT (in INTEGER_CST). + TREE_INDIRECT_USING (in NAMESPACE_DECL). + IDENTIFIER_MARKED (used by search routines). + LOCAL_BINDING_P (in CPLUS_BINDING) + 1: IDENTIFIER_VIRTUAL_P. + TI_PENDING_TEMPLATE_FLAG. + TEMPLATE_PARMS_FOR_INLINE. + DELETE_EXPR_USE_VEC (in DELETE_EXPR). + (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out). + TYPE_USES_COMPLEX_INHERITANCE (in _TYPE). + C_DECLARED_LABEL_FLAG. + INHERITED_VALUE_BINDING_P (in CPLUS_BINDING) + BASELINK_P (in TREE_LIST) + 2: IDENTIFIER_OPNAME_P. + BINFO_VBASE_MARKED. + BINFO_FIELDS_MARKED. + TYPE_VIRTUAL_P. + 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE). + BINFO_VTABLE_PATH_MARKED. + BINFO_PUSHDECLS_MARKED. + (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). + 4: BINFO_NEW_VTABLE_MARKED. + TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, + or FIELD_DECL). + 5: TYPE_USES_PVBASES (in a class TYPE). + 6: Not used. + + Usage of TYPE_LANG_FLAG_?: + 0: C_TYPE_FIELDS_READONLY (in RECORD_TYPE or UNION_TYPE). + 1: TYPE_HAS_CONSTRUCTOR. + 2: TYPE_HAS_DESTRUCTOR. + 3: TYPE_FOR_JAVA. + 4: TYPE_NEEDS_DESTRUCTOR. + 5: IS_AGGR_TYPE. + 6: TYPE_BUILT_IN. + + Usage of DECL_LANG_FLAG_?: + 0: DECL_ERROR_REPORTED (in VAR_DECL). + DECL_TEMPLATE_PARM_P (in CONST_DECL, TYPE_DECL, or TEMPLATE_DECL) + 1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL). + DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL) + 2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL). + 3: DECL_IN_AGGR_P. + 4: DECL_MAYBE_TEMPLATE. + 5: DECL_INTERFACE_KNOWN. + 6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL). + 7: DECL_DEAD_FOR_LOCAL (in VAR_DECL). + + Usage of language-independent fields in a language-dependent manner: + + TYPE_ALIAS_SET + This field is used by TYPENAME_TYPEs, TEMPLATE_TYPE_PARMs, and so + forth as a substitute for the mark bits provided in `lang_type'. + At present, only the six low-order bits are used. + + TYPE_BINFO + For an ENUMERAL_TYPE, this is ENUM_TEMPLATE_INFO. + For a TYPENAME_TYPE, this is TYPENAME_TYPE_FULLNAME. + For a TEMPLATE_TEMPLATE_PARM, this is + TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO. + + DECL_SAVED_INSNS/DECL_FIELD_SIZE + For a static VAR_DECL, this is DECL_INIT_PRIORITY. +*/ + +/* Language-dependent contents of an identifier. */ + +struct lang_identifier +{ + struct tree_identifier ignore; + tree namespace_bindings; + tree bindings; + tree class_value; + tree class_template_info; + struct lang_id2 *x; +}; + +struct lang_id2 +{ + tree label_value, implicit_decl; + tree error_locus; +}; + +typedef struct +{ + tree t; + int new_type_flag; +} flagged_type_tree; + +typedef struct +{ + char common[sizeof (struct tree_common)]; + struct rtx_def *rtl; /* Unused, but required to match up with what + the middle-end expects. */ + HOST_WIDE_INT index; + HOST_WIDE_INT level; + HOST_WIDE_INT orig_level; + tree decl; +} template_parm_index; + +typedef struct ptrmem_cst +{ + char common[sizeof (struct tree_common)]; + tree member; +}* ptrmem_cst_t; + +/* Nonzero if this binding is for a local scope, as opposed to a class + or namespace scope. */ +#define LOCAL_BINDING_P(NODE) TREE_LANG_FLAG_0(NODE) + +/* Nonzero if BINDING_VALUE is from a base class of the class which is + currently being defined. */ +#define INHERITED_VALUE_BINDING_P(NODE) TREE_LANG_FLAG_1(NODE) + +/* For a binding between a name and an entity at a non-local scope, + defines the scope where the binding is declared. (Either a class + _TYPE node, or a NAMESPACE_DECL.) This macro should be used only + for namespace-level bindings; on the IDENTIFIER_BINDING list + BINDING_LEVEL is used instead. */ +#define BINDING_SCOPE(NODE) (((struct tree_binding*)NODE)->scope.scope) + +/* This is the declaration bound to the name. Possible values: + variable, overloaded function, namespace, template, enumerator. */ +#define BINDING_VALUE(NODE) (((struct tree_binding*)NODE)->value) + +/* If name is bound to a type, this is the type (struct, union, enum). */ +#define BINDING_TYPE(NODE) TREE_TYPE(NODE) + +#define IDENTIFIER_GLOBAL_VALUE(NODE) \ + namespace_binding (NODE, global_namespace) +#define SET_IDENTIFIER_GLOBAL_VALUE(NODE, VAL) \ + set_namespace_binding (NODE, global_namespace, VAL) +#define IDENTIFIER_NAMESPACE_VALUE(NODE) \ + namespace_binding (NODE, current_namespace) +#define SET_IDENTIFIER_NAMESPACE_VALUE(NODE, VAL) \ + set_namespace_binding (NODE, current_namespace, VAL) + +struct tree_binding +{ + char common[sizeof (struct tree_common)]; + union { + tree scope; + struct binding_level *level; + } scope; + tree value; +}; + +/* The overloaded FUNCTION_DECL. */ +#define OVL_FUNCTION(NODE) (((struct tree_overload*)NODE)->function) +#define OVL_CHAIN(NODE) TREE_CHAIN(NODE) +/* Polymorphic access to FUNCTION and CHAIN. */ +#define OVL_CURRENT(NODE) \ + ((TREE_CODE(NODE)==OVERLOAD) ? OVL_FUNCTION(NODE) : NODE) +#define OVL_NEXT(NODE) \ + ((TREE_CODE(NODE)==OVERLOAD) ? TREE_CHAIN(NODE) : NULL_TREE) +/* If set, this was imported in a using declaration. + This is not to confuse with being used somewhere, which + is not important for this node. */ +#define OVL_USED(NODE) TREE_USED(NODE) + +struct tree_overload +{ + char common[sizeof (struct tree_common)]; + tree function; +}; + +/* A `baselink' is a TREE_LIST whose TREE_PURPOSE is a BINFO + indicating a particular base class, and whose TREE_VALUE is a + (possibly overloaded) function from that base class. */ +#define BASELINK_P(NODE) \ + (TREE_CODE ((NODE)) == TREE_LIST && TREE_LANG_FLAG_1 ((NODE))) +#define SET_BASELINK_P(NODE) \ + (TREE_LANG_FLAG_1 ((NODE)) = 1) + +#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)NODE)->u.ptr) +#define WRAPPER_INT(NODE) (((struct tree_wrapper*)NODE)->u.i) + +struct tree_wrapper +{ + char common[sizeof (struct tree_common)]; + union { + void *ptr; + int i; + } u; +}; + +#define SRCLOC_FILE(NODE) (((struct tree_srcloc*)NODE)->filename) +#define SRCLOC_LINE(NODE) (((struct tree_srcloc*)NODE)->linenum) +struct tree_srcloc +{ + char common[sizeof (struct tree_common)]; + char *filename; + int linenum; +}; + +/* To identify to the debug emitters if it should pay attention to the + flag `-Wtemplate-debugging'. */ +#define HAVE_TEMPLATES 1 + +/* Macros for access to language-specific slots in an identifier. */ + +#define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \ + (((struct lang_identifier *)(NODE))->namespace_bindings) +#define IDENTIFIER_TEMPLATE(NODE) \ + (((struct lang_identifier *)(NODE))->class_template_info) + +/* The IDENTIFIER_BINDING is the innermost CPLUS_BINDING for the + identifier. It's TREE_CHAIN is the next outermost binding. Each + BINDING_VALUE is a DECL for the associated declaration. Thus, + name lookup consists simply of pulling off the node at the front + of the list (modulo oddities for looking up the names of types, + and such.) You can use BINDING_SCOPE or BINDING_LEVEL to + determine the scope that bound the name. */ +#define IDENTIFIER_BINDING(NODE) \ + (((struct lang_identifier*) (NODE))->bindings) + +/* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or + NULL_TREE if there is no binding. */ +#define IDENTIFIER_VALUE(NODE) \ + (IDENTIFIER_BINDING (NODE) \ + ? BINDING_VALUE (IDENTIFIER_BINDING (NODE)) \ + : NULL_TREE) + +/* If IDENTIFIER_CLASS_VALUE is set, then NODE is bound in the current + class, and IDENTIFIER_CLASS_VALUE is the value binding. This is + just a pointer to the BINDING_VALUE of one of the bindings in the + IDENTIFIER_BINDINGs list, so any time that this is non-NULL so is + IDENTIFIER_BINDING. */ +#define IDENTIFIER_CLASS_VALUE(NODE) \ + (((struct lang_identifier *) (NODE))->class_value) + +/* The amount of time used by the file whose special "time identifier" + is NODE, represented as an INTEGER_CST. See get_time_identifier. */ +#define TIME_IDENTIFIER_TIME(NODE) IDENTIFIER_BINDING(NODE) + +/* For a "time identifier" this is a INTEGER_CST. The + TREE_INT_CST_LOW is 1 if the corresponding file is "interface only". + The TRE_INT_CST_HIGH is 1 if it is "interface unknown". */ +#define TIME_IDENTIFIER_FILEINFO(NODE) IDENTIFIER_CLASS_VALUE (NODE) + +/* TREE_TYPE only indicates on local and class scope the current + type. For namespace scope, the presence of a type in any namespace + is indicated with global_type_node, and the real type behind must + be found through lookup. */ +#define IDENTIFIER_TYPE_VALUE(NODE) (identifier_type_value(NODE)) +#define REAL_IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (NODE)) +#define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (TREE_TYPE (NODE) = TYPE) +#define IDENTIFIER_HAS_TYPE_VALUE(NODE) (IDENTIFIER_TYPE_VALUE (NODE) ? 1 : 0) + +#define LANG_ID_FIELD(NAME,NODE) \ + (((struct lang_identifier *)(NODE))->x \ + ? ((struct lang_identifier *)(NODE))->x->NAME : 0) +#define SET_LANG_ID(NODE,VALUE,NAME) \ + (((struct lang_identifier *)(NODE))->x == 0 \ + ? ((struct lang_identifier *)(NODE))->x \ + = (struct lang_id2 *)perm_calloc (1, sizeof (struct lang_id2)) : 0, \ + ((struct lang_identifier *)(NODE))->x->NAME = (VALUE)) + +#define IDENTIFIER_LABEL_VALUE(NODE) LANG_ID_FIELD(label_value, NODE) +#define SET_IDENTIFIER_LABEL_VALUE(NODE,VALUE) \ + SET_LANG_ID(NODE, VALUE, label_value) + +#define IDENTIFIER_IMPLICIT_DECL(NODE) LANG_ID_FIELD(implicit_decl, NODE) +#define SET_IDENTIFIER_IMPLICIT_DECL(NODE,VALUE) \ + SET_LANG_ID(NODE, VALUE, implicit_decl) + +#define IDENTIFIER_ERROR_LOCUS(NODE) LANG_ID_FIELD(error_locus, NODE) +#define SET_IDENTIFIER_ERROR_LOCUS(NODE,VALUE) \ + SET_LANG_ID(NODE, VALUE, error_locus) + + +#define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1(NODE) + +/* Nonzero if this identifier is the prefix for a mangled C++ operator name. */ +#define IDENTIFIER_OPNAME_P(NODE) TREE_LANG_FLAG_2(NODE) + +/* Nonzero if this identifier is the name of a type-conversion + operator. */ +#define IDENTIFIER_TYPENAME_P(NODE) \ + (! strncmp (IDENTIFIER_POINTER (NODE), \ + OPERATOR_TYPENAME_FORMAT, \ + strlen (OPERATOR_TYPENAME_FORMAT))) + +/* Nonzero means reject anything that ANSI standard C forbids. */ +extern int pedantic; + +/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */ +#define C_TYPE_FIELDS_READONLY(type) TYPE_LANG_FLAG_0 (type) + +/* Record in each node resulting from a binary operator + what operator was specified for it. */ +#define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp)) + +/* Store a value in that field. */ +#define C_SET_EXP_ORIGINAL_CODE(exp, code) \ + (TREE_COMPLEXITY (exp) = (int)(code)) + +/* If non-zero, a VAR_DECL whose cleanup will cause a throw to the + next exception handler. */ +extern tree exception_throw_decl; + +extern tree double_type_node, long_double_type_node, float_type_node; +extern tree char_type_node, unsigned_char_type_node, signed_char_type_node; +extern tree ptrdiff_type_node; + +extern tree short_integer_type_node, short_unsigned_type_node; +extern tree long_integer_type_node, long_unsigned_type_node; +extern tree long_long_integer_type_node, long_long_unsigned_type_node; +extern tree unsigned_type_node; +extern tree string_type_node, char_array_type_node, int_array_type_node; +extern tree wchar_array_type_node; +extern tree wchar_type_node, signed_wchar_type_node, unsigned_wchar_type_node; + +extern tree complex_integer_type_node; +extern tree complex_float_type_node; +extern tree complex_double_type_node; +extern tree complex_long_double_type_node; + +extern tree intQI_type_node, unsigned_intQI_type_node; +extern tree intHI_type_node, unsigned_intHI_type_node; +extern tree intSI_type_node, unsigned_intSI_type_node; +extern tree intDI_type_node, unsigned_intDI_type_node; +#if HOST_BITS_PER_WIDE_INT >= 64 +extern tree intTI_type_node, unsigned_intTI_type_node; +#endif + +extern tree java_byte_type_node; +extern tree java_short_type_node; +extern tree java_int_type_node; +extern tree java_long_type_node; +extern tree java_float_type_node; +extern tree java_double_type_node; +extern tree java_char_type_node; +extern tree java_boolean_type_node; + +extern int current_function_returns_value; +extern int current_function_returns_null; +extern tree current_function_return_value; + +extern tree current_namespace; +extern tree global_namespace; + +extern tree ridpointers[]; +extern tree ansi_opname[]; +extern tree ansi_assopname[]; + +/* Nonzero means `$' can be in an identifier. */ + +extern int dollars_in_ident; + +/* Nonzero means allow type mismatches in conditional expressions; + just make their values `void'. */ + +extern int flag_cond_mismatch; + +/* Nonzero means don't recognize the keyword `asm'. */ + +extern int flag_no_asm; + +/* For cross referencing. */ + +extern int flag_gnu_xref; + +/* For environments where you can use GNU binutils (as, ld in particular). */ + +extern int flag_gnu_binutils; + +/* Nonzero means warn about implicit declarations. */ + +extern int warn_implicit; + +/* Nonzero means warn about usage of long long when `-pedantic'. */ + +extern int warn_long_long; + +/* Nonzero means warn when all ctors or dtors are private, and the class + has no friends. */ + +extern int warn_ctor_dtor_privacy; + +/* Nonzero means warn about function definitions that default the return type + or that use a null return and have a return-type other than void. */ + +extern int warn_return_type; + +/* Nonzero means give string constants the type `const char *', as mandated + by the standard. */ + +extern int flag_const_strings; + +/* Nonzero means warn about deprecated conversion from string constant to + `char *'. */ + +extern int warn_write_strings; + +/* Nonzero means warn about sizeof(function) or addition/subtraction + of function pointers. */ + +extern int warn_pointer_arith; + +/* Nonzero means warn about suggesting putting in ()'s. */ + +extern int warn_parentheses; + +/* Nonzero means warn about multiple (redundant) decls for the same single + variable or function. */ + +extern int warn_redundant_decls; + +/* Warn if initializer is not completely bracketed. */ + +extern int warn_missing_braces; + +/* Warn about comparison of signed and unsigned values. */ + +extern int warn_sign_compare; + +/* Warn about a subscript that has type char. */ + +extern int warn_char_subscripts; + +/* Nonzero means warn about pointer casts that can drop a type qualifier + from the pointer target type. */ + +extern int warn_cast_qual; + +/* Warn about *printf or *scanf format/argument anomalies. */ + +extern int warn_format; + +/* Nonzero means warn about non virtual destructors in classes that have + virtual functions. */ + +extern int warn_nonvdtor; + +/* Non-zero means warn when we convert a pointer to member function + into a pointer to (void or function). */ + +extern int warn_pmf2ptr; + +/* Nonzero means warn about violation of some Effective C++ style rules. */ + +extern int warn_ecpp; + +/* Nonzero means warn where overload resolution chooses a promotion from + unsigned to signed over a conversion to an unsigned of the same size. */ + +extern int warn_sign_promo; + +/* Non-zero means warn when a function is declared extern and later inline. */ + +extern int warn_extern_inline; + +/* Non-zero means warn when an old-style cast is used. */ + +extern int warn_old_style_cast; + +/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */ + +extern int flag_signed_bitfields; + +/* 3 means write out only virtuals function tables `defined' + in this implementation file. + 2 means write out only specific virtual function tables + and give them (C) public access. + 1 means write out virtual function tables and give them + (C) public access. + 0 means write out virtual function tables and give them + (C) static access (default). + -1 means declare virtual function tables extern. */ + +extern int write_virtuals; + +/* True for more efficient but incompatible (not fully tested) + vtable implementation (using thunks). + 0 is old behavior; 1 is new behavior; 3 adds vlist arguments; + 2 is 3 plus backwards-compatibility to 1. */ +extern int flag_vtable_thunks, flag_vtable_thunks_compat; + +/* INTERFACE_ONLY nonzero means that we are in an "interface" + section of the compiler. INTERFACE_UNKNOWN nonzero means + we cannot trust the value of INTERFACE_ONLY. If INTERFACE_UNKNOWN + is zero and INTERFACE_ONLY is zero, it means that we are responsible + for exporting definitions that others might need. */ +extern int interface_only, interface_unknown; + +/* Nonzero means we should attempt to elide constructors when possible. */ + +extern int flag_elide_constructors; + +/* Nonzero means enable obscure ANSI features and disable GNU extensions + that might cause ANSI-compliant code to be miscompiled. */ + +extern int flag_ansi; + +/* Nonzero means recognize and handle signature language constructs. */ + +extern int flag_handle_signatures; + +/* Nonzero means that member functions defined in class scope are + inline by default. */ + +extern int flag_default_inline; + +/* The name-mangling scheme to use. Versions of gcc before 2.8 use + version 0. */ +extern int name_mangling_version; + +/* Nonzero means that guiding declarations are allowed. */ +extern int flag_guiding_decls; + +/* Nonzero if squashed mangling is to be performed. + This uses the B and K codes to reference previously seen class types + and class qualifiers. */ +extern int flag_do_squangling; + +/* Nonzero means generate separate instantiation control files and juggle + them at link time. */ +extern int flag_use_repository; + +/* Nonzero if we want to issue diagnostics that the standard says are not + required. */ +extern int flag_optional_diags; + +/* Nonzero means do not consider empty argument prototype to mean function + takes no arguments. */ +extern int flag_strict_prototype; + +/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */ +extern int flag_vtable_gc; + +/* Nonzero means make the default pedwarns warnings instead of errors. + The value of this flag is ignored if -pedantic is specified. */ +extern int flag_permissive; + +/* Nonzero if we want to obey access control semantics. */ + +extern int flag_access_control; + + +/* C++ language-specific tree codes. */ +#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM, +enum cplus_tree_code { + __DUMMY = LAST_AND_UNUSED_TREE_CODE, +#include "cp-tree.def" + LAST_CPLUS_TREE_CODE +}; +#undef DEFTREECODE + +enum languages { lang_c, lang_cplusplus, lang_java }; + +/* Macros to make error reporting functions' lives easier. */ +#define TYPE_IDENTIFIER(NODE) (DECL_NAME (TYPE_NAME (NODE))) +#define TYPE_NAME_STRING(NODE) (IDENTIFIER_POINTER (TYPE_IDENTIFIER (NODE))) +#define TYPE_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (TYPE_IDENTIFIER (NODE))) + +#define TYPE_ASSEMBLER_NAME_STRING(NODE) (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE)))) +#define TYPE_ASSEMBLER_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE)))) + +/* The _DECL for this _TYPE. */ +#define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE))) + +/* Nonzero if T is a class (or struct or union) type. Also nonzero + for template type parameters and typename types. Despite its name, + this macro has nothing to do with the definition of aggregate given + in the standard. Think of this macro as MAYBE_CLASS_TYPE_P. */ +#define IS_AGGR_TYPE(t) \ + (TREE_CODE (t) == TEMPLATE_TYPE_PARM \ + || TREE_CODE (t) == TYPENAME_TYPE \ + || TREE_CODE (t) == TYPEOF_TYPE \ + || TYPE_LANG_FLAG_5 (t)) + +/* Set IS_AGGR_TYPE for T to VAL. T must be a class, struct, or + union type. */ +#define SET_IS_AGGR_TYPE(T, VAL) \ + (TYPE_LANG_FLAG_5 (T) = (VAL)) + +/* Nonzero if T is a class type. Zero for template type parameters, + typename types, and so forth. */ +#define CLASS_TYPE_P(t) \ + (IS_AGGR_TYPE_CODE (TREE_CODE (t)) && IS_AGGR_TYPE (t)) + +#define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE) +#define IS_AGGR_TYPE_2(TYPE1,TYPE2) \ + (TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \ + && IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2)) +#define IS_OVERLOAD_TYPE(t) \ + (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE) + +/* In a *_TYPE, nonzero means a built-in type. */ +#define TYPE_BUILT_IN(NODE) TYPE_LANG_FLAG_6(NODE) + +/* True if this a "Java" type, defined in 'extern "Java"'. */ +#define TYPE_FOR_JAVA(NODE) TYPE_LANG_FLAG_3(NODE) + +/* The type qualifiers for this type, including the qualifiers on the + elements for an array type. */ +#define CP_TYPE_QUALS(NODE) \ + ((TREE_CODE (NODE) != ARRAY_TYPE) \ + ? TYPE_QUALS (NODE) : cp_type_quals (NODE)) + +/* Nonzero if this type is const-qualified. */ +#define CP_TYPE_CONST_P(NODE) \ + ((CP_TYPE_QUALS (NODE) & TYPE_QUAL_CONST) != 0) + +/* Nonzero if this type is volatile-qualified. */ +#define CP_TYPE_VOLATILE_P(NODE) \ + ((CP_TYPE_QUALS (NODE) & TYPE_QUAL_VOLATILE) != 0) + +/* Nonzero if this type is restrict-qualified. */ +#define CP_TYPE_RESTRICT_P(NODE) \ + ((CP_TYPE_QUALS (NODE) & TYPE_QUAL_RESTRICT) != 0) + +/* Nonzero if this type is const-qualified, but not + volatile-qualified. Other qualifiers are ignored. This macro is + used to test whether or not it is OK to bind an rvalue to a + reference. */ +#define CP_TYPE_CONST_NON_VOLATILE_P(NODE) \ + ((CP_TYPE_QUALS (NODE) & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) \ + == TYPE_QUAL_CONST) + +#define DELTA_FROM_VTABLE_ENTRY(ENTRY) \ + (!flag_vtable_thunks ? \ + TREE_VALUE (CONSTRUCTOR_ELTS (ENTRY)) \ + : TREE_CODE (TREE_OPERAND ((ENTRY), 0)) != THUNK_DECL ? integer_zero_node \ + : build_int_2 (THUNK_DELTA (TREE_OPERAND ((ENTRY), 0)), 0)) + +/* Virtual function addresses can be gotten from a virtual function + table entry using this macro. */ +#define FNADDR_FROM_VTABLE_ENTRY(ENTRY) \ + (!flag_vtable_thunks ? \ + TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) \ + : TREE_CODE (TREE_OPERAND ((ENTRY), 0)) != THUNK_DECL ? (ENTRY) \ + : DECL_INITIAL (TREE_OPERAND ((ENTRY), 0))) +#define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \ + (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) = (VALUE)) +#define FUNCTION_ARG_CHAIN(NODE) (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE)))) +#define PROMOTES_TO_AGGR_TYPE(NODE,CODE) \ + (((CODE) == TREE_CODE (NODE) \ + && IS_AGGR_TYPE (TREE_TYPE (NODE))) \ + || IS_AGGR_TYPE (NODE)) + +/* Nonzero iff TYPE is uniquely derived from PARENT. Under MI, PARENT can + be an ambiguous base class of TYPE, and this macro will be false. */ +#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) >= 0) +#define ACCESSIBLY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, -1, (tree *)0) >= 0) +#define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 1, (tree *)0) >= 0) +#define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1) + +/* This structure provides additional information above and beyond + what is provide in the ordinary tree_type. In the past, we used it + for the types of class types, template parameters types, typename + types, and so forth. However, there can be many (tens to hundreds + of thousands) of template parameter types in a compilation, and + there's no need for this additional information in that case. + Therefore, we now use this data structure only for class types. + + In the past, it was thought that there would be relatively few + class types. However, in the presence of heavy use of templates, + many (i.e., thousands) of classes can easily be generated. + Therefore, we should endeavor to keep the size of this structure to + a minimum. */ +struct lang_type +{ + struct + { + unsigned has_type_conversion : 1; + unsigned has_init_ref : 1; + unsigned has_default_ctor : 1; + unsigned uses_multiple_inheritance : 1; + unsigned const_needs_init : 1; + unsigned ref_needs_init : 1; + unsigned has_const_assign_ref : 1; + unsigned anon_union : 1; + + unsigned has_nonpublic_ctor : 2; + unsigned has_nonpublic_assign_ref : 2; + unsigned vtable_needs_writing : 1; + unsigned has_assign_ref : 1; + unsigned gets_new : 2; + + unsigned gets_delete : 2; + unsigned has_call_overloaded : 1; + unsigned has_array_ref_overloaded : 1; + unsigned has_arrow_overloaded : 1; + unsigned interface_only : 1; + unsigned interface_unknown : 1; + unsigned needs_virtual_reinit : 1; + + unsigned marks: 6; + unsigned vec_delete_takes_size : 1; + unsigned declared_class : 1; + + unsigned being_defined : 1; + unsigned redefined : 1; + unsigned debug_requested : 1; + unsigned use_template : 2; + unsigned got_semicolon : 1; + unsigned ptrmemfunc_flag : 1; + unsigned is_signature : 1; + + unsigned is_signature_pointer : 1; + unsigned is_signature_reference : 1; + unsigned has_opaque_typedecls : 1; + unsigned sigtable_has_been_generated : 1; + unsigned was_anonymous : 1; + unsigned has_real_assign_ref : 1; + unsigned has_const_init_ref : 1; + unsigned has_complex_init_ref : 1; + + unsigned has_complex_assign_ref : 1; + unsigned has_abstract_assign_ref : 1; + unsigned non_aggregate : 1; + unsigned is_partial_instantiation : 1; + unsigned has_mutable : 1; + unsigned com_interface : 1; + /* When adding a flag here, consider whether or not it ought to + apply to a template instance if it applies to the template. + If so, make sure to copy it in instantiate_class_template! */ + + /* The MIPS compiler gets it wrong if this struct also + does not fill out to a multiple of 4 bytes. Add a + member `dummy' with new bits if you go over the edge. */ + unsigned dummy : 10; + } type_flags; + + int vsize; + int vfield_parent; + + union tree_node *vfields; + union tree_node *vbases; + + union tree_node *tags; + + union tree_node *search_slot; + + unsigned char align; + /* Room for another three unsigned chars. */ + + union tree_node *size; + + union tree_node *abstract_virtuals; + union tree_node *friend_classes; + + union tree_node *rtti; + + union tree_node *methods; + + union tree_node *signature; + union tree_node *signature_pointer_to; + union tree_node *signature_reference_to; + union tree_node *template_info; + tree befriending_classes; +}; + +/* Indicates whether or not (and how) a template was expanded for this class. + 0=no information yet/non-template class + 1=implicit template instantiation + 2=explicit template specialization + 3=explicit template instantiation */ +#define CLASSTYPE_USE_TEMPLATE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.use_template) + +/* Fields used for storing information before the class is defined. + After the class is defined, these fields hold other information. */ + +/* List of friends which were defined inline in this class definition. */ +#define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE)) + +/* Nonzero for _CLASSTYPE means that operator new and delete are defined, + respectively. */ +#define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new) +#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_delete) +#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1) + +/* Nonzero for _CLASSTYPE means that operator vec delete is defined and + takes the optional size_t argument. */ +#define TYPE_VEC_DELETE_TAKES_SIZE(NODE) \ + (TYPE_LANG_SPECIFIC(NODE)->type_flags.vec_delete_takes_size) +#define TYPE_VEC_NEW_USES_COOKIE(NODE) \ + (TYPE_NEEDS_DESTRUCTOR (NODE) \ + || (TYPE_LANG_SPECIFIC (NODE) && TYPE_VEC_DELETE_TAKES_SIZE (NODE))) + +/* Nonzero means that this _CLASSTYPE node defines ways of converting + itself to other types. */ +#define TYPE_HAS_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_type_conversion) + +/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */ +#define TYPE_HAS_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_assign_ref) +#define TYPE_HAS_CONST_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_const_assign_ref) + +/* Nonzero means that this _CLASSTYPE node has an X(X&) constructor. */ +#define TYPE_HAS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_init_ref) +#define TYPE_HAS_CONST_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_const_init_ref) + +/* Nonzero means that this type is being defined. I.e., the left brace + starting the definition of this type has been seen. */ +#define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.being_defined) +/* Nonzero means that this type has been redefined. In this case, if + convenient, don't reprocess any methods that appear in its redefinition. */ +#define TYPE_REDEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.redefined) + +/* Nonzero means that this type is a signature. */ +# define IS_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)?TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature:0) +# define SET_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature=1) +# define CLEAR_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature=0) + +/* Nonzero means that this type is a signature pointer type. */ +# define IS_SIGNATURE_POINTER(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature_pointer) + +/* Nonzero means that this type is a signature reference type. */ +# define IS_SIGNATURE_REFERENCE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature_reference) + +/* Nonzero means that this signature contains opaque type declarations. */ +#define SIGNATURE_HAS_OPAQUE_TYPEDECLS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_opaque_typedecls) + +/* Nonzero means that a signature table has been generated + for this signature. */ +#define SIGTABLE_HAS_BEEN_GENERATED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.sigtable_has_been_generated) + +/* If NODE is a class, this is the signature type that contains NODE's + signature after it has been computed using sigof(). */ +#define CLASSTYPE_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)->signature) + +/* If NODE is a signature pointer or signature reference, this is the + signature type the pointer/reference points to. */ +#define SIGNATURE_TYPE(NODE) (TYPE_LANG_SPECIFIC(NODE)->signature) + +/* If NODE is a signature, this is a vector of all methods defined + in the signature or in its base types together with their default + implementations. */ +#define SIGNATURE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->signature) + +/* If NODE is a signature, this is the _TYPE node that contains NODE's + signature pointer type. */ +#define SIGNATURE_POINTER_TO(NODE) (TYPE_LANG_SPECIFIC(NODE)->signature_pointer_to) + +/* If NODE is a signature, this is the _TYPE node that contains NODE's + signature reference type. */ +#define SIGNATURE_REFERENCE_TO(NODE) (TYPE_LANG_SPECIFIC(NODE)->signature_reference_to) + +/* The is the basetype that contains NODE's rtti. */ +#define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC(NODE)->rtti) + +/* Nonzero means that this _CLASSTYPE node overloads operator(). */ +#define TYPE_OVERLOADS_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_call_overloaded) + +/* Nonzero means that this _CLASSTYPE node overloads operator[]. */ +#define TYPE_OVERLOADS_ARRAY_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_array_ref_overloaded) + +/* Nonzero means that this _CLASSTYPE node overloads operator->. */ +#define TYPE_OVERLOADS_ARROW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_arrow_overloaded) + +/* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses + multiple inheritance. If this is 0 for the root of a type + hierarchy, then we can use more efficient search techniques. */ +#define TYPE_USES_MULTIPLE_INHERITANCE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.uses_multiple_inheritance) + +/* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses + virtual base classes. If this is 0 for the root of a type + hierarchy, then we can use more efficient search techniques. */ +#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE)) + +/* Nonzero means that this _CLASSTYPE uses polymorphic virtual bases. + This flag is set only when we use vtable thunks. */ +#define TYPE_USES_PVBASES(NODE) (TREE_LANG_FLAG_5(NODE)) + +/* Vector member functions defined in this class. Each element is + either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All + functions with the same name end up in the same slot. The first + two elements are for constructors, and destructors, respectively. + These are followed by ordinary member functions. There may be + empty entries at the end of the vector. */ +#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods) + +/* The first type conversion operator in the class (the others can be + searched with TREE_CHAIN), or the first non-constructor function if + there are no type conversion operators. */ +#define CLASSTYPE_FIRST_CONVERSION(NODE) \ + TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 2 \ + ? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 2) \ + : NULL_TREE; + +/* Mark bits for depth-first and breath-first searches. */ + +/* Get the value of the Nth mark bit. */ +#define CLASSTYPE_MARKED_N(NODE, N) \ + (((CLASS_TYPE_P (NODE) ? TYPE_LANG_SPECIFIC (NODE)->type_flags.marks \ + : TYPE_ALIAS_SET (NODE)) & (1 << N)) != 0) + +/* Set the Nth mark bit. */ +#define SET_CLASSTYPE_MARKED_N(NODE, N) \ + (CLASS_TYPE_P (NODE) \ + ? (TYPE_LANG_SPECIFIC (NODE)->type_flags.marks |= (1 << (N))) \ + : (TYPE_ALIAS_SET (NODE) |= (1 << (N)))) + +/* Clear the Nth mark bit. */ +#define CLEAR_CLASSTYPE_MARKED_N(NODE, N) \ + (CLASS_TYPE_P (NODE) \ + ? (TYPE_LANG_SPECIFIC (NODE)->type_flags.marks &= ~(1 << (N))) \ + : (TYPE_ALIAS_SET (NODE) &= ~(1 << (N)))) + +/* Get the value of the mark bits. */ +#define CLASSTYPE_MARKED(NODE) CLASSTYPE_MARKED_N(NODE, 0) +#define CLASSTYPE_MARKED2(NODE) CLASSTYPE_MARKED_N(NODE, 1) +#define CLASSTYPE_MARKED3(NODE) CLASSTYPE_MARKED_N(NODE, 2) +#define CLASSTYPE_MARKED4(NODE) CLASSTYPE_MARKED_N(NODE, 3) +#define CLASSTYPE_MARKED5(NODE) CLASSTYPE_MARKED_N(NODE, 4) +#define CLASSTYPE_MARKED6(NODE) CLASSTYPE_MARKED_N(NODE, 5) + +/* Macros to modify the above flags */ +#define SET_CLASSTYPE_MARKED(NODE) SET_CLASSTYPE_MARKED_N(NODE, 0) +#define CLEAR_CLASSTYPE_MARKED(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 0) +#define SET_CLASSTYPE_MARKED2(NODE) SET_CLASSTYPE_MARKED_N(NODE, 1) +#define CLEAR_CLASSTYPE_MARKED2(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 1) +#define SET_CLASSTYPE_MARKED3(NODE) SET_CLASSTYPE_MARKED_N(NODE, 2) +#define CLEAR_CLASSTYPE_MARKED3(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 2) +#define SET_CLASSTYPE_MARKED4(NODE) SET_CLASSTYPE_MARKED_N(NODE, 3) +#define CLEAR_CLASSTYPE_MARKED4(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 3) +#define SET_CLASSTYPE_MARKED5(NODE) SET_CLASSTYPE_MARKED_N(NODE, 4) +#define CLEAR_CLASSTYPE_MARKED5(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 4) +#define SET_CLASSTYPE_MARKED6(NODE) SET_CLASSTYPE_MARKED_N(NODE, 5) +#define CLEAR_CLASSTYPE_MARKED6(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 5) + +/* A list of the nested tag-types (class, struct, union, or enum) + found within this class. The TREE_PURPOSE of each node is the name + of the type; the TREE_VALUE is the type itself. This list includes + nested member class templates. */ +#define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC(NODE)->tags) + +/* If this class has any bases, this is the number of the base class from + which our VFIELD is based, -1 otherwise. If this class has no base + classes, this is not used. + In D : B1, B2, PARENT would be 0, if D's vtable came from B1, + 1, if D's vtable came from B2. */ +#define CLASSTYPE_VFIELD_PARENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfield_parent) + +/* Remove when done merging. */ +#define CLASSTYPE_VFIELD(NODE) TYPE_VFIELD(NODE) + +/* The number of virtual functions defined for this + _CLASSTYPE node. */ +#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize) +/* The list of binfos of virtual base classes that this type uses. */ +#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases) +/* The virtual function pointer fields that this type contains. */ +#define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields) + +/* Number of baseclasses defined for this type. + 0 means no base classes. */ +#define CLASSTYPE_N_BASECLASSES(NODE) \ + (TYPE_BINFO_BASETYPES (NODE) ? TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES(NODE)) : 0) + +/* Used for keeping search-specific information. Any search routine + which uses this must define what exactly this slot is used for. */ +#define CLASSTYPE_SEARCH_SLOT(NODE) (TYPE_LANG_SPECIFIC(NODE)->search_slot) + +/* These are the size, mode and alignment of the type without its + virtual base classes, for when we use this type as a base itself. */ +#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size) +#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align) + +/* A cons list of virtual functions which cannot be inherited by + derived classes. When deriving from this type, the derived + class must provide its own definition for each of these functions. */ +#define CLASSTYPE_ABSTRACT_VIRTUALS(NODE) (TYPE_LANG_SPECIFIC(NODE)->abstract_virtuals) + +/* Nonzero means that this aggr type has been `closed' by a semicolon. */ +#define CLASSTYPE_GOT_SEMICOLON(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.got_semicolon) + +/* Nonzero means that the main virtual function table pointer needs to be + set because base constructors have placed the wrong value there. + If this is zero, it means that they placed the right value there, + and there is no need to change it. */ +#define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.needs_virtual_reinit) + +/* Nonzero means that if this type has virtual functions, that + the virtual function table will be written out. */ +#define CLASSTYPE_VTABLE_NEEDS_WRITING(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.vtable_needs_writing) + +/* Nonzero means that this type has an X() constructor. */ +#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_default_ctor) + +/* Nonzero means the type declared a ctor as private or protected. We + use this to make sure we don't try to generate a copy ctor for a + class that has a member of type NODE. */ +#define TYPE_HAS_NONPUBLIC_CTOR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_nonpublic_ctor) + +/* Ditto, for operator=. */ +#define TYPE_HAS_NONPUBLIC_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_nonpublic_assign_ref) + +/* Nonzero means that this type contains a mutable member */ +#define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_mutable) +#define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE)) + +/* Nonzero means that this type is meant for communication via COM. */ +#define CLASSTYPE_COM_INTERFACE(NODE) \ + (TYPE_LANG_SPECIFIC(NODE)->type_flags.com_interface) + +/* A list of class types of which this type is a friend. The + TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the + case of a template friend. */ +#define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes) + +/* A list of the classes which grant friendship to this class. */ +#define CLASSTYPE_BEFRIENDING_CLASSES(NODE) \ + (TYPE_LANG_SPECIFIC (NODE)->befriending_classes) + +/* Say whether this node was declared as a "class" or a "struct". */ +#define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class) + +/* Nonzero if this class has const members which have no specified initialization. */ +#define CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.const_needs_init) + +/* Nonzero if this class has ref members which have no specified initialization. */ +#define CLASSTYPE_REF_FIELDS_NEED_INIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.ref_needs_init) + +/* Nonzero if this class is included from a header file which employs + `#pragma interface', and it is not included in its implementation file. */ +#define CLASSTYPE_INTERFACE_ONLY(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.interface_only) + +/* Same as above, but for classes whose purpose we do not know. */ +#define CLASSTYPE_INTERFACE_UNKNOWN(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.interface_unknown) +#define CLASSTYPE_INTERFACE_KNOWN(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.interface_unknown == 0) +#define SET_CLASSTYPE_INTERFACE_UNKNOWN_X(NODE,X) (TYPE_LANG_SPECIFIC(NODE)->type_flags.interface_unknown = !!(X)) +#define SET_CLASSTYPE_INTERFACE_UNKNOWN(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.interface_unknown = 1) +#define SET_CLASSTYPE_INTERFACE_KNOWN(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.interface_unknown = 0) + +/* Nonzero if a _DECL node requires us to output debug info for this class. */ +#define CLASSTYPE_DEBUG_REQUESTED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.debug_requested) + +/* Additional macros for inheritance information. */ + +/* The BINFO_INHERITANCE_CHAIN is used opposite to the description in + gcc/tree.h. In particular if D is derived from B then the BINFO + for B (in D) will have a BINFO_INHERITANCE_CHAIN pointing to + D. In tree.h, this pointer is described as pointing in other + direction. There is a different BINFO for each path to a virtual + base; BINFOs for virtual bases are not shared. In addition, shared + versions of each of the virtual class BINFOs are stored in + CLASSTYPE_VBASECLASSES. + + We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private + inheritance is indicated by the absence of the other two flags, not + by TREE_VIAR_PRIVATE, which is unused. + + The TREE_CHAIN is for scratch space in search.c. */ + +/* Nonzero means marked by DFS or BFS search, including searches + by `get_binfo' and `get_base_distance'. */ +#define BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED(BINFO_TYPE(NODE)):TREE_LANG_FLAG_0(NODE)) +/* Macros needed because of C compilers that don't allow conditional + expressions to be lvalues. Grr! */ +#define SET_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=1)) +#define CLEAR_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=0)) + +/* Nonzero means marked in search through virtual inheritance hierarchy. */ +#define BINFO_VBASE_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE)) +/* Modifier macros */ +#define SET_BINFO_VBASE_MARKED(NODE) SET_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE)) +#define CLEAR_BINFO_VBASE_MARKED(NODE) CLEAR_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE)) + +/* Nonzero means marked in search for members or member functions. */ +#define BINFO_FIELDS_MARKED(NODE) \ + (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED2 (BINFO_TYPE (NODE)):TREE_LANG_FLAG_2(NODE)) +#define SET_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=1)) +#define CLEAR_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=0)) + +/* Nonzero means that this class is on a path leading to a new vtable. */ +#define BINFO_VTABLE_PATH_MARKED(NODE) \ + (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):TREE_LANG_FLAG_3(NODE)) +#define SET_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=1)) +#define CLEAR_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=0)) + +/* Nonzero means that this class has a new vtable. */ +#define BINFO_NEW_VTABLE_MARKED(NODE) \ + (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):TREE_LANG_FLAG_4(NODE)) +#define SET_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=1)) +#define CLEAR_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=0)) + +/* Nonzero means this class has done dfs_pushdecls. */ +#define BINFO_PUSHDECLS_MARKED(NODE) BINFO_VTABLE_PATH_MARKED (NODE) +#define SET_BINFO_PUSHDECLS_MARKED(NODE) SET_BINFO_VTABLE_PATH_MARKED (NODE) +#define CLEAR_BINFO_PUSHDECLS_MARKED(NODE) CLEAR_BINFO_VTABLE_PATH_MARKED (NODE) + +/* Used by various search routines. */ +#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE) + +/* Accessor macros for the vfield slots in structures. */ + +/* Get the assoc info that caused this vfield to exist. */ +#define VF_BINFO_VALUE(NODE) TREE_PURPOSE (NODE) + +/* Get that same information as a _TYPE. */ +#define VF_BASETYPE_VALUE(NODE) TREE_VALUE (NODE) + +/* Get the value of the top-most type dominating the non-`normal' vfields. */ +#define VF_DERIVED_VALUE(NODE) (VF_BINFO_VALUE (NODE) ? BINFO_TYPE (VF_BINFO_VALUE (NODE)) : NULL_TREE) + +/* Get the value of the top-most type that's `normal' for the vfield. */ +#define VF_NORMAL_VALUE(NODE) TREE_TYPE (NODE) + +/* Nonzero for TREE_LIST node means that this list of things + is a list of parameters, as opposed to a list of expressions. */ +#define TREE_PARMLIST(NODE) ((NODE)->common.unsigned_flag) /* overloaded! */ + +/* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that + this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE + will be NULL_TREE to indicate a throw specification of `(...)', or, + equivalently, no throw specification. */ +#define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE) + +/* For FUNCTION_TYPE or METHOD_TYPE, return 1 iff it is declared `throw()'. */ +#define TYPE_NOTHROW_P(NODE) \ + (TYPE_RAISES_EXCEPTIONS (NODE) \ + && TREE_VALUE (TYPE_RAISES_EXCEPTIONS (NODE)) == NULL_TREE) + +/* The binding level associated with the namespace. */ +#define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level) + + +/* If a DECL has DECL_LANG_SPECIFIC, it is either a lang_decl_flags or + a lang_decl (which has lang_decl_flags as its initial prefix). A + FUNCTION_DECL, NAMESPACE_DECL, TYPE_DECL, or USING_DECL may have a + full lang_decl. A FIELD_DECL, or a static data member VAR_DECL, + will have only lang_decl_flags. Thus, one should only access the + members of lang_decl that are not in lang_decl_flags for DECLs that + are not FIELD_DECLs or VAR_DECLs. */ + +struct lang_decl_flags +{ +#ifdef ONLY_INT_FIELDS + int language : 8; +#else + enum languages language : 8; +#endif + + unsigned operator_attr : 1; + unsigned constructor_attr : 1; + unsigned friend_attr : 1; + unsigned static_function : 1; + unsigned const_memfunc : 1; + unsigned volatile_memfunc : 1; + unsigned abstract_virtual : 1; + unsigned permanent_attr : 1 ; + + unsigned mutable_flag : 1; + unsigned is_default_implementation : 1; + unsigned saved_inline : 1; + unsigned use_template : 2; + unsigned nonconverting : 1; + unsigned declared_inline : 1; + unsigned not_really_extern : 1; + unsigned needs_final_overrider : 1; + unsigned bitfield : 1; + unsigned defined_in_class : 1; + unsigned constructor_for_vbase_attr : 2; + unsigned dummy : 3; + + tree access; + tree context; + tree memfunc_pointer_to; + tree template_info; + struct binding_level *level; +}; + +struct lang_decl +{ + struct lang_decl_flags decl_flags; + + tree main_decl_variant; + tree befriending_classes; + struct pending_inline *pending_inline_info; +}; + +/* Non-zero if NODE is a _DECL with TREE_READONLY set. */ +#define TREE_READONLY_DECL_P(NODE) \ + (TREE_READONLY (NODE) && TREE_CODE_CLASS (TREE_CODE (NODE)) == 'd') + +/* Non-zero iff DECL is memory-based. The DECL_RTL of + certain const variables might be a CONST_INT, or a REG + in some cases. We cannot use `memory_operand' as a test + here because on most RISC machines, a variable's address + is not, by itself, a legitimate address. */ +#define DECL_IN_MEMORY_P(NODE) \ + (DECL_RTL (NODE) != NULL_RTX && GET_CODE (DECL_RTL (NODE)) == MEM) + +/* For FUNCTION_DECLs: return the language in which this decl + was declared. */ +#define DECL_LANGUAGE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.language) + +/* For FUNCTION_DECLs: nonzero means that this function is a constructor. */ +#define DECL_CONSTRUCTOR_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_attr) + +/* There ought to be a better way to find out whether or not something is + a destructor. */ +#define DECL_DESTRUCTOR_P(NODE) \ + (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (NODE)) \ + && DECL_LANGUAGE (NODE) == lang_cplusplus) + +#define DECL_CONV_FN_P(NODE) \ + (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_NAME (NODE))) + +#define CONSTRUCTOR_FOR_VBASE 1 +#define CONSTRUCTOR_FOR_PVBASE 2 +#define DESTRUCTOR_FOR_PVBASE 3 + +/* For FUNCTION_DECLs: nonzero means that this function is a con/destructor + for an object with virtual baseclasses. */ +#define DECL_CONSTRUCTOR_FOR_VBASE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr) + +/* Nonzero means that this function is a constructor for an object + with virtual baseclasses. */ +#define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) \ + (DECL_CONSTRUCTOR_FOR_VBASE (NODE) == CONSTRUCTOR_FOR_VBASE) + +/* Nonzero means that this function is a constructor for an object + with virtual baseclasses which have virtual functions. */ +#define DECL_CONSTRUCTOR_FOR_PVBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr == CONSTRUCTOR_FOR_PVBASE) + +/* Nonzero means that this function is a destructor for an object + with virtual baseclasses which have virtual functions. */ +#define DECL_DESTRUCTOR_FOR_PVBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr == DESTRUCTOR_FOR_PVBASE) + +/* Nonzero means that this function is a wrapper around a PVBASE ctor. */ +#define DECL_VLIST_CTOR_WRAPPER_P(NODE) \ + (DECL_CONSTRUCTOR_FOR_VBASE_P (NODE) && DECL_VLIST_CTOR_WRAPPED (NODE)\ + && TREE_CODE (DECL_VLIST_CTOR_WRAPPED (NODE)) == FUNCTION_DECL \ + && DECL_CONSTRUCTOR_FOR_PVBASE_P (DECL_VLIST_CTOR_WRAPPED (NODE))) + +/* Refers to original function that NODE wraps. */ +#define DECL_VLIST_CTOR_WRAPPED(NODE) DECL_MEMFUNC_POINTER_TO (NODE) + +/* Non-zero for a FUNCTION_DECL that declares a type-info function. */ +#define DECL_TINFO_FN_P(NODE) \ + (TREE_CODE (NODE) == FUNCTION_DECL \ + && DECL_ARTIFICIAL (NODE) \ + && DECL_LANG_SPECIFIC(NODE)->decl_flags.mutable_flag) + +/* Mark NODE as a type-info function. */ +#define SET_DECL_TINFO_FN_P(NODE) \ + (DECL_LANG_SPECIFIC((NODE))->decl_flags.mutable_flag = 1) + +/* For FUNCTION_DECLs: nonzero means that this function is a default + implementation of a signature method. */ +#define IS_DEFAULT_IMPLEMENTATION(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.is_default_implementation) + +/* Nonzero for _DECL means that this decl appears in (or will appear + in) as a member in a RECORD_TYPE or UNION_TYPE node. It is also for + detecting circularity in case members are multiply defined. In the + case of a VAR_DECL, it is also used to determine how program storage + should be allocated. */ +#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3(NODE)) + +/* Nonzero if the DECL was defined in the class definition itself, + rather than outside the class. */ +#define DECL_DEFINED_IN_CLASS_P(DECL) \ + (DECL_LANG_SPECIFIC (DECL)->decl_flags.defined_in_class) + +/* Nonzero for FUNCTION_DECL means that this decl is just a + friend declaration, and should not be added to the list of + member functions for this class. */ +#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.friend_attr) + +/* A TREE_LIST of the types which have befriended this FUNCTION_DECL. */ +#define DECL_BEFRIENDING_CLASSES(NODE) \ + (DECL_LANG_SPECIFIC(NODE)->befriending_classes) + +/* Nonzero for FUNCTION_DECL means that this decl is a static + member function. */ +#define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function) + +/* Nonzero for a class member means that it is shared between all objects + of that class. */ +#define SHARED_MEMBER_P(NODE) \ + (TREE_CODE (NODE) == VAR_DECL || TREE_CODE (NODE) == TYPE_DECL \ + || TREE_CODE (NODE) == CONST_DECL) + +/* Nonzero for FUNCTION_DECL means that this decl is a non-static + member function. */ +#define DECL_NONSTATIC_MEMBER_FUNCTION_P(NODE) \ + (TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE) + +/* Nonzero for FUNCTION_DECL means that this decl is a member function + (static or non-static). */ +#define DECL_FUNCTION_MEMBER_P(NODE) \ + (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE) || DECL_STATIC_FUNCTION_P (NODE)) + +/* Nonzero for FUNCTION_DECL means that this member function + has `this' as const X *const. */ +#define DECL_CONST_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.const_memfunc) + +/* Nonzero for FUNCTION_DECL means that this member function + has `this' as volatile X *const. */ +#define DECL_VOLATILE_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.volatile_memfunc) + +/* Nonzero for a DECL means that this member is a non-static member. */ +#define DECL_NONSTATIC_MEMBER_P(NODE) \ + ((TREE_CODE (NODE) == FUNCTION_DECL \ + && DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE)) \ + || TREE_CODE (NODE) == FIELD_DECL) + +/* Nonzero for _DECL means that this member object type + is mutable. */ +#define DECL_MUTABLE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.mutable_flag) + +/* Nonzero for _DECL means that this constructor is a non-converting + constructor. */ +#define DECL_NONCONVERTING_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.nonconverting) + +/* Nonzero for FUNCTION_DECL means that this member function + exists as part of an abstract class's interface. */ +#define DECL_ABSTRACT_VIRTUAL_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.abstract_virtual) + +/* Nonzero for FUNCTION_DECL means that this member function + must be overridden by derived classes. */ +#define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.needs_final_overrider) + +/* Nonzero if allocated on permanent_obstack. */ +#define LANG_DECL_PERMANENT(LANGDECL) ((LANGDECL)->decl_flags.permanent_attr) + +/* The _TYPE context in which this _DECL appears. This field holds the + class where a virtual function instance is actually defined, and the + lexical scope of a friend function defined in a class body. */ +#define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context) +#define DECL_REAL_CONTEXT(NODE) \ + ((TREE_CODE (NODE) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (NODE)) \ + ? DECL_CLASS_CONTEXT (NODE) : CP_DECL_CONTEXT (NODE)) + +/* NULL_TREE in DECL_CONTEXT represents the global namespace. */ +#define CP_DECL_CONTEXT(NODE) \ + (DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace) +#define FROB_CONTEXT(NODE) ((NODE) == global_namespace ? NULL_TREE : (NODE)) + +/* For a virtual function, the base where we find its vtable entry. + For a non-virtual function, the base where it is defined. */ +#define DECL_VIRTUAL_CONTEXT(NODE) DECL_CONTEXT (NODE) + +/* 1 iff NODE has namespace scope, including the global namespace. */ +#define DECL_NAMESPACE_SCOPE_P(NODE) \ + (DECL_CONTEXT (NODE) == NULL_TREE \ + || TREE_CODE (DECL_CONTEXT (NODE)) == NAMESPACE_DECL) + +/* 1 iff NODE is a class member. */ +#define DECL_CLASS_SCOPE_P(NODE) \ + (DECL_CONTEXT (NODE) \ + && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (NODE))) == 't') + +/* 1 iff NODE is function-local. */ +#define DECL_FUNCTION_SCOPE_P(NODE) \ + (DECL_CONTEXT (NODE) \ + && TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL) + +/* For a NAMESPACE_DECL: the list of using namespace directives + The PURPOSE is the used namespace, the value is the namespace + that is the common ancestor. */ +#define DECL_NAMESPACE_USING(NODE) DECL_VINDEX(NODE) + +/* In a NAMESPACE_DECL, the DECL_INITIAL is used to record all users + of a namespace, to record the transitive closure of using namespace. */ +#define DECL_NAMESPACE_USERS(NODE) DECL_INITIAL (NODE) + +/* In a NAMESPACE_DECL, points to the original namespace if this is + a namespace alias. */ +#define DECL_NAMESPACE_ALIAS(NODE) DECL_ABSTRACT_ORIGIN (NODE) +#define ORIGINAL_NAMESPACE(NODE) \ + (DECL_NAMESPACE_ALIAS (NODE) ? DECL_NAMESPACE_ALIAS (NODE) : (NODE)) + +/* In a non-local VAR_DECL with static storage duration, this is the + initialization priority. If this value is zero, the NODE will be + initialized at the DEFAULT_INIT_PRIORITY. */ +#define DECL_INIT_PRIORITY(NODE) (DECL_FIELD_SIZE ((NODE))) + +/* In a TREE_LIST concatenating using directives, indicate indirekt + directives */ +#define TREE_INDIRECT_USING(NODE) ((NODE)->common.lang_flag_0) + +/* In a VAR_DECL for a variable declared in a for statement, + this is the shadowed (local) variable. */ +#define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE) + +/* Points back to the decl which caused this lang_decl to be allocated. */ +#define DECL_MAIN_VARIANT(NODE) (DECL_LANG_SPECIFIC(NODE)->main_decl_variant) + +/* For a FUNCTION_DECL: if this function was declared inline inside of + a class declaration, this is where the text for the function is + squirreled away. */ +#define DECL_PENDING_INLINE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->pending_inline_info) + +/* True if on the saved_inlines (see decl2.c) list. */ +#define DECL_SAVED_INLINE(DECL) \ + (DECL_LANG_SPECIFIC(DECL)->decl_flags.saved_inline) + +/* For a FUNCTION_DECL: if this function was declared inside a signature + declaration, this is the corresponding member function pointer that was + created for it. */ +#define DECL_MEMFUNC_POINTER_TO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.memfunc_pointer_to) + +/* For a FIELD_DECL: this points to the signature member function from + which this signature member function pointer was created. */ +#define DECL_MEMFUNC_POINTING_TO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.memfunc_pointer_to) + +/* For a VAR_DECL or FUNCTION_DECL: template-specific information. */ +#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.template_info) + +/* Template information for a RECORD_TYPE or UNION_TYPE. */ +#define CLASSTYPE_TEMPLATE_INFO(NODE) (TYPE_LANG_SPECIFIC(NODE)->template_info) + +/* Template information for an ENUMERAL_TYPE. Although an enumeration may + not be a primary template, it may be declared within the scope of a + primary template and the enumeration constants may depend on + non-type template parameters. */ +#define ENUM_TEMPLATE_INFO(NODE) (TYPE_BINFO (NODE)) + +/* Template information for a template template parameter. */ +#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) (TYPE_BINFO (NODE)) + +/* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE. */ +#define TYPE_TEMPLATE_INFO(NODE) \ + (TREE_CODE (NODE) == ENUMERAL_TYPE \ + ? ENUM_TEMPLATE_INFO (NODE) : \ + (TREE_CODE (NODE) == TEMPLATE_TEMPLATE_PARM \ + ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) \ + : CLASSTYPE_TEMPLATE_INFO (NODE))) + +/* Set the template information for an ENUMERAL_, RECORD_, or + UNION_TYPE to VAL. */ +#define SET_TYPE_TEMPLATE_INFO(NODE, VAL) \ + (TREE_CODE (NODE) == ENUMERAL_TYPE \ + ? (ENUM_TEMPLATE_INFO (NODE) = VAL) \ + : (CLASSTYPE_TEMPLATE_INFO (NODE) = VAL)) + +#define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE)) +#define TI_ARGS(NODE) (TREE_VALUE (NODE)) +#define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE)) +#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) + +/* The TEMPLATE_DECL instantiated or specialized by NODE. This + TEMPLATE_DECL will be the immediate parent, not the most general + template. For example, in: + + template struct S { template void f(U); } + + the FUNCTION_DECL for S::f will have, as its + DECL_TI_TEMPLATE, `template S::f'. + + As a special case, for a member friend template of a template + class, this value will not be a TEMPLATE_DECL, but rather a + LOOKUP_EXPR or IDENTIFIER_NODE indicating the name of the template + and any explicit template arguments provided. For example, in: + + template struct S { friend void f(int, double); } + + the DECL_TI_TEMPLATE will be a LOOKUP_EXPR for `f' and the + DECL_TI_ARGS will be {int}. */ +#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE)) + +/* The template arguments used to obtain this decl from the most + general form of DECL_TI_TEMPLATE. For the example given for + DECL_TI_TEMPLATE, the DECL_TI_ARGS will be {int, double}. These + are always the full set of arguments required to instantiate this + declaration from the most general template specialized here. */ +#define DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE)) +#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE)) +#define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE)) +#define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (CLASSTYPE_TEMPLATE_INFO (NODE)) +#define ENUM_TI_TEMPLATE(NODE) \ + TI_TEMPLATE (ENUM_TEMPLATE_INFO (NODE)) +#define ENUM_TI_ARGS(NODE) \ + TI_ARGS (ENUM_TEMPLATE_INFO (NODE)) + +/* Like DECL_TI_TEMPLATE, but for an ENUMERAL_, RECORD_, or UNION_TYPE. */ +#define TYPE_TI_TEMPLATE(NODE) \ + (TI_TEMPLATE (TYPE_TEMPLATE_INFO (NODE))) + +/* Like DECL_TI_ARGS, , but for an ENUMERAL_, RECORD_, or UNION_TYPE. */ +#define TYPE_TI_ARGS(NODE) \ + (TI_ARGS (TYPE_TEMPLATE_INFO (NODE))) + +#define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE) + +/* Nonzero if the NODE corresponds to the template parameters for a + member template, whose inline definition is being processed after + the class definition is complete. */ +#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE) + +#define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE) +#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE) +#define NEW_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE) +#define DELETE_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE) +#define DELETE_EXPR_USE_VEC(NODE) TREE_LANG_FLAG_1 (NODE) +#define LOOKUP_EXPR_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE) + +/* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a + TEMPLATE_DECL. This macro determines whether or not a given class + type is really a template type, as opposed to an instantiation or + specialization of one. */ +#define CLASSTYPE_IS_TEMPLATE(NODE) \ + (CLASSTYPE_TEMPLATE_INFO (NODE) \ + && !CLASSTYPE_USE_TEMPLATE (NODE) \ + && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))) + +/* The name used by the user to name the typename type. Typically, + this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the + corresponding TYPE_DECL. However, this may also be a + TEMPLATE_ID_EXPR if we had something like `typename X::Y'. */ +#define TYPENAME_TYPE_FULLNAME(NODE) TYPE_BINFO (NODE) + +/* Nonzero if NODE is an implicit typename. */ +#define IMPLICIT_TYPENAME_P(NODE) \ + (TREE_CODE (NODE) == TYPENAME_TYPE && TREE_TYPE (NODE)) + +/* Nonzero in INTEGER_CST means that this int is negative by dint of + using a twos-complement negated operand. */ +#define TREE_NEGATED_INT(NODE) (TREE_LANG_FLAG_0 (NODE)) + +#if 0 /* UNUSED */ +/* Nonzero in any kind of _EXPR or _REF node means that it is a call + to a storage allocation routine. If, later, alternate storage + is found to hold the object, this call can be ignored. */ +#define TREE_CALLS_NEW(NODE) (TREE_LANG_FLAG_1 (NODE)) +#endif + +/* Nonzero in any kind of _TYPE that uses multiple inheritance + or virtual baseclasses. */ +#define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE)) + +#if 0 /* UNUSED */ +/* Nonzero in IDENTIFIER_NODE means that this name is not the name the user + gave; it's a DECL_NESTED_TYPENAME. Someone may want to set this on + mangled function names, too, but it isn't currently. */ +#define TREE_MANGLED(NODE) (FOO) +#endif + +#if 0 /* UNUSED */ +/* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and + should be looked up in a non-standard way. */ +#define DECL_OVERLOADED(NODE) (FOO) +#endif + +/* Nonzero if this (non-TYPE)_DECL has its virtual attribute set. + For a FUNCTION_DECL, this is when the function is a virtual function. + For a VAR_DECL, this is when the variable is a virtual function table. + For a FIELD_DECL, when the field is the field for the virtual function table. + For an IDENTIFIER_NODE, nonzero if any function with this name + has been declared virtual. + + For a _TYPE if it uses virtual functions (or is derived from + one that does). */ +#define TYPE_VIRTUAL_P(NODE) (TREE_LANG_FLAG_2 (NODE)) + +extern int flag_new_for_scope; + +/* This flag is true of a local VAR_DECL if it was declared in a for + statement, but we are no longer in the scope of the for. */ +#define DECL_DEAD_FOR_LOCAL(NODE) DECL_LANG_FLAG_7 (NODE) + +/* This flag is set on a VAR_DECL that is a DECL_DEAD_FOR_LOCAL + if we already emitted a warning about using it. */ +#define DECL_ERROR_REPORTED(NODE) DECL_LANG_FLAG_0 (NODE) + +/* This _DECL represents a compiler-generated entity. */ +#define SET_DECL_ARTIFICIAL(NODE) (DECL_ARTIFICIAL (NODE) = 1) + +/* Record whether a typedef for type `int' was actually `signed int'. */ +#define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp)) + +/* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */ +#define DECL_C_BIT_FIELD(NODE) \ + (DECL_LANG_SPECIFIC (NODE) && DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield) +#define SET_DECL_C_BIT_FIELD(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield = 1) + +/* Nonzero if the type T promotes to itself. + ANSI C states explicitly the list of types that promote; + in particular, short promotes to int even if they have the same width. */ +#define C_PROMOTING_INTEGER_TYPE_P(t) \ + (TREE_CODE ((t)) == INTEGER_TYPE \ + && (TYPE_MAIN_VARIANT (t) == char_type_node \ + || TYPE_MAIN_VARIANT (t) == signed_char_type_node \ + || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node \ + || TYPE_MAIN_VARIANT (t) == short_integer_type_node \ + || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node)) + +#define INTEGRAL_CODE_P(CODE) \ + (CODE == INTEGER_TYPE || CODE == ENUMERAL_TYPE || CODE == BOOLEAN_TYPE) +#define ARITHMETIC_TYPE_P(TYPE) (INTEGRAL_TYPE_P (TYPE) || FLOAT_TYPE_P (TYPE)) + +/* Mark which labels are explicitly declared. + These may be shadowed, and may be referenced from nested functions. */ +#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label) + +/* Nonzero for _TYPE means that the _TYPE defines + at least one constructor. */ +#define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1(NODE)) + +/* When appearing in an INDIRECT_REF, it means that the tree structure + underneath is actually a call to a constructor. This is needed + when the constructor must initialize local storage (which can + be automatically destroyed), rather than allowing it to allocate + space from the heap. + + When appearing in a SAVE_EXPR, it means that underneath + is a call to a constructor. + + When appearing in a CONSTRUCTOR, it means that it was + a GNU C constructor expression. + + When appearing in a FIELD_DECL, it means that this field + has been duly initialized in its constructor. */ +#define TREE_HAS_CONSTRUCTOR(NODE) (TREE_LANG_FLAG_4(NODE)) + +#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ + && CONSTRUCTOR_ELTS (NODE) == NULL_TREE \ + && ! TREE_HAS_CONSTRUCTOR (NODE)) + +#if 0 +/* Indicates that a NON_LVALUE_EXPR came from a C++ reference. + Used to generate more helpful error message in case somebody + tries to take its address. */ +#define TREE_REFERENCE_EXPR(NODE) (TREE_LANG_FLAG_3(NODE)) +#endif + +/* Nonzero for _TYPE means that the _TYPE defines a destructor. */ +#define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE)) + +#if 0 +/* Nonzero for _TYPE node means that creating an object of this type + will involve a call to a constructor. This can apply to objects + of ARRAY_TYPE if the type of the elements needs a constructor. */ +#define TYPE_NEEDS_CONSTRUCTING(NODE) ... defined in ../tree.h ... +#endif + +/* Nonzero means that an object of this type can not be initialized using + an initializer list. */ +#define CLASSTYPE_NON_AGGREGATE(NODE) \ + (TYPE_LANG_SPECIFIC (NODE)->type_flags.non_aggregate) +#define TYPE_NON_AGGREGATE_CLASS(NODE) \ + (IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE)) + +/* Nonzero if there is a user-defined X::op=(x&) for this class. */ +#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assign_ref) +#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_assign_ref) +#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_abstract_assign_ref) +#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_init_ref) + +/* Nonzero for _TYPE node means that destroying an object of this type + will involve a call to a destructor. This can apply to objects + of ARRAY_TYPE is the type of the elements needs a destructor. */ +#define TYPE_NEEDS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_4(NODE)) + +/* Nonzero for class type means that initialization of this type can use + a bitwise copy. */ +#define TYPE_HAS_TRIVIAL_INIT_REF(NODE) \ + (TYPE_HAS_INIT_REF (NODE) && ! TYPE_HAS_COMPLEX_INIT_REF (NODE)) + +/* Nonzero for class type means that assignment of this type can use + a bitwise copy. */ +#define TYPE_HAS_TRIVIAL_ASSIGN_REF(NODE) \ + (TYPE_HAS_ASSIGN_REF (NODE) && ! TYPE_HAS_COMPLEX_ASSIGN_REF (NODE)) + +#define TYPE_PTRMEM_P(NODE) \ + (TREE_CODE (NODE) == POINTER_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) == OFFSET_TYPE) +#define TYPE_PTR_P(NODE) \ + (TREE_CODE (NODE) == POINTER_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) != OFFSET_TYPE) +#define TYPE_PTROB_P(NODE) \ + (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE) +#define TYPE_PTROBV_P(NODE) \ + (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE) +#define TYPE_PTRFN_P(NODE) \ + (TREE_CODE (NODE) == POINTER_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE) + +/* Nonzero for _TYPE node means that this type is a pointer to member + function type. */ +#define TYPE_PTRMEMFUNC_P(NODE) \ + (TREE_CODE(NODE) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (NODE)) +#define TYPE_PTRMEMFUNC_FLAG(NODE) \ + (TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag) + +/* A pointer-to-function member type looks like: + + struct { + short __delta; + short __index; + union { + P __pfn; + short __delta2; + } __pfn_or_delta2; + }; + + where P is a POINTER_TYPE to a METHOD_TYPE appropriate for the + pointer to member. The fields are used as follows: + + If __INDEX is -1, then the function to call is non-virtual, and + is located at the address given by __PFN. + + If __INDEX is zero, then this a NULL pointer-to-member. + + Otherwise, the function to call is virtual. Then, __DELTA2 gives + the offset from an instance of the object to the virtual function + table, and __INDEX - 1 is the index into the vtable to use to + find the function. + + The value to use for the THIS parameter is the address of the + object plus __DELTA. + + For example, given: + + struct B1 { + int i; + }; + + struct B2 { + double d; + void f(); + }; + + struct S : public B1, B2 {}; + + the pointer-to-member for `&S::f' looks like: + + { 4, -1, { &f__2B2 } }; + + The `4' means that given an `S*' you have to add 4 bytes to get to + the address of the `B2*'. Then, the -1 indicates that this is a + non-virtual function. Of course, `&f__2B2' is the name of that + function. + + (Of course, the exactl values may differ depending on the mangling + scheme, sizes of types, and such.). */ + +/* Get the POINTER_TYPE to the METHOD_TYPE associated with this + pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true, + before using this macro. */ +#define TYPE_PTRMEMFUNC_FN_TYPE(NODE) (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (NODE))))))) + +/* Returns `A' for a type like `int (A::*)(double)' */ +#define TYPE_PTRMEMFUNC_OBJECT_TYPE(NODE) \ + TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (NODE))) + +/* These are use to manipulate the canonical RECORD_TYPE from the + hashed POINTER_TYPE, and can only be used on the POINTER_TYPE. */ +#define TYPE_GET_PTRMEMFUNC_TYPE(NODE) ((tree)TYPE_LANG_SPECIFIC(NODE)) +#define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE) (TYPE_LANG_SPECIFIC(NODE) = ((struct lang_type *)(void*)(VALUE))) +/* These are to get the delta2 and pfn fields from a TYPE_PTRMEMFUNC_P. */ +#define DELTA2_FROM_PTRMEMFUNC(NODE) delta2_from_ptrmemfunc ((NODE)) +#define PFN_FROM_PTRMEMFUNC(NODE) pfn_from_ptrmemfunc ((NODE)) + +/* For a pointer-to-member constant `X::Y' this is the RECORD_TYPE for + `X'. */ +#define PTRMEM_CST_CLASS(NODE) \ + (TYPE_PTRMEM_P (TREE_TYPE (NODE)) \ + ? TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (NODE))) \ + : TYPE_PTRMEMFUNC_OBJECT_TYPE (TREE_TYPE (NODE))) + +/* For a pointer-to-member constant `X::Y' this is the _DECL for + `Y'. */ +#define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t) NODE)->member) + +/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was + specified in its declaration. */ +#define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE)) + +/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `static' was + specified in its declaration. */ +#define DECL_THIS_STATIC(NODE) (DECL_LANG_FLAG_6(NODE)) + +/* Nonzero in FUNCTION_DECL means it is really an operator. + Just used to communicate formatting information to dbxout.c. */ +#define DECL_OPERATOR(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.operator_attr) + +#define ANON_UNION_P(NODE) (DECL_NAME (NODE) == 0) + +/* Nonzero if TYPE is an anonymous union type. We have to use a flag for + this because "A union for which objects or pointers are declared is not + an anonymous union" [class.union]. */ +#define ANON_UNION_TYPE_P(NODE) \ + (TYPE_LANG_SPECIFIC (NODE) \ + && TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_union) +#define SET_ANON_UNION_TYPE_P(NODE) \ + (TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_union = 1) + +#define UNKNOWN_TYPE LANG_TYPE + +/* Define fields and accessors for nodes representing declared names. */ + +#if 0 +/* C++: A derived class may be able to directly use the virtual + function table of a base class. When it does so, it may + still have a decl node used to access the virtual function + table (so that variables of this type can initialize their + virtual function table pointers by name). When such thievery + is committed, know exactly which base class's virtual function + table is the one being stolen. This effectively computes the + transitive closure. */ +#define DECL_VPARENT(NODE) ((NODE)->decl.arguments) +#endif + +#define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.was_anonymous) + +/* C++: all of these are overloaded! These apply only to TYPE_DECLs. */ + +/* The format of each node in the DECL_FRIENDLIST is as follows: + + The TREE_PURPOSE will be the name of a function, i.e., an + IDENTIFIER_NODE. The TREE_VALUE will be itself a TREE_LIST, the + list of functions with that name which are friends. The + TREE_PURPOSE of each node in this sublist will be error_mark_node, + if the function was declared a friend individually, in which case + the TREE_VALUE will be the function_decl. If, however, all + functions with a given name in a class were declared to be friends, + the TREE_PUROSE will be the class type, and the TREE_VALUE will be + NULL_TREE. */ +#define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE)) +#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST)) +#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST)) + +/* The DECL_ACCESS, if non-NULL, is a TREE_LIST. The TREE_PURPOSE of + each node is a type; the TREE_VALUE is the access granted for this + DECL in that type. The DECL_ACCESS is set by access declarations. + For example, if a member that would normally be public in a + derived class is made protected, then the derived class and the + protected_access_node will appear in the DECL_ACCESS for the node. */ +#define DECL_ACCESS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.access) + +/* C++: all of these are overloaded! + These apply to PARM_DECLs and VAR_DECLs. */ +#define DECL_REFERENCE_SLOT(NODE) ((tree)(NODE)->decl.arguments) +#define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL) + +/* Accessor macros for C++ template decl nodes. */ + +/* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node + is a INT_CST whose TREE_INT_CST_HIGH indicates the level of the + template parameters, with 1 being the outermost set of template + parameters. The TREE_VALUE is a vector, whose elements are the + template parameters at each level. Each element in the vector is a + TREE_LIST, whose TREE_VALUE is a PARM_DECL (if the parameter is a + non-type parameter), or a TYPE_DECL (if the parameter is a type + parameter). The TREE_PURPOSE is the default value, if any. The + TEMPLATE_PARM_INDEX for the parameter is avilable as the + DECL_INITIAL (for a PARM_DECL) or as the TREE_TYPE (for a + TYPE_DECL). */ +#define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE) +#define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \ + INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE)) +#define DECL_NTPARMS(NODE) \ + TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) +/* For function, method, class-data templates. */ +#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE) +/* For a static member variable template, the + DECL_TEMPLATE_INSTANTIATIONS list contains the explicitly and + implicitly generated instantiations of the variable. There are no + partial instantiations of static member variables, so all of these + will be full instantiations. + + For a class template the DECL_TEMPLATE_INSTANTIATIONS lists holds + all instantiations and specializations of the class type, including + partial instantiations and partial specializations. + + In both cases, the TREE_PURPOSE of each node contains the arguments + used; the TREE_VALUE contains the generated variable. The template + arguments are always complete. For example, given: + + template struct S1 { + template struct S2 {}; + template struct S2 {}; + }; + + the record for the partial specialization will contain, as its + argument list, { {T}, {U*} }, and will be on the + DECL_TEMPLATE_INSTANTIATIONS list for `template template + struct S1::S2'. + + This list is not used for function templates. */ +#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE) +/* For a function template, the DECL_TEMPLATE_SPECIALIZATIONS lists + contains all instantiations and specializations of the function, + including partial instantiations. For a partial instantiation + which is a specialization, this list holds only full + specializations of the template that are instantiations of the + partial instantiation. For example, given: + + template struct S { + template void f(U); + template <> void f(T); + }; + + the `S::f(int)' function will appear on the + DECL_TEMPLATE_SPECIALIZATIONS list for both `template + template void S::f(U)' and `template void + S::f(T)'. In the latter case, however, it will have only the + innermost set of arguments (T, in this case). The DECL_TI_TEMPLATE + for the function declaration will point at the specialization, not + the fully general template. + + For a class template, this list contains the partial + specializations of this template. (Full specializations are not + recorded on this list.) The TREE_PURPOSE holds the innermost + arguments used in the partial specialization (e.g., for `template + struct S' this will be `T*'.) The TREE_VALUE + holds the innermost template parameters for the specialization + (e.g., `T' in the example above.) The TREE_TYPE is the _TYPE node + for the partial specialization. + + This list is not used for static variable templates. */ +#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE) +#define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE) + +/* Nonzero for a DECL which is actually a template parameter. */ +#define DECL_TEMPLATE_PARM_P(NODE) \ + DECL_LANG_FLAG_0 (NODE) + +#define DECL_TEMPLATE_TEMPLATE_PARM_P(NODE) \ + (TREE_CODE (NODE) == TEMPLATE_DECL && DECL_TEMPLATE_PARM_P (NODE)) + +#define DECL_FUNCTION_TEMPLATE_P(NODE) \ + (TREE_CODE (NODE) == TEMPLATE_DECL \ + && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL) + +/* Nonzero for a DECL that represents a template class. */ +#define DECL_CLASS_TEMPLATE_P(NODE) \ + (TREE_CODE (NODE) == TEMPLATE_DECL \ + && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL \ + && !DECL_TEMPLATE_TEMPLATE_PARM_P (NODE)) + +/* Nonzero if NODE which declares a type. */ +#define DECL_DECLARES_TYPE_P(NODE) \ + (TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE)) + +/* A `primary' template is one that has its own template header. A + member function of a class template is a template, but not primary. + A member template is primary. Friend templates are primary, too. */ + +/* Returns the primary template corresponding to these parameters. */ +#define DECL_PRIMARY_TEMPLATE(NODE) \ + (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE))) + +/* Returns non-zero if NODE is a primary template. */ +#define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == NODE) + +#define CLASSTYPE_TEMPLATE_LEVEL(NODE) \ + (TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE)))) + +/* Indicates whether or not (and how) a template was expanded for this + FUNCTION_DECL or VAR_DECL. + 0=normal declaration, e.g. int min (int, int); + 1=implicit template instantiation + 2=explicit template specialization, e.g. int min (int, int); + 3=explicit template instantiation, e.g. template int min (int, int); */ +#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.use_template) + +#define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1) +#define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE (NODE) & 1) + +#define DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) == 2) +#define SET_DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) = 2) +#define CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE (NODE) == 2) +#define SET_CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE (NODE) = 2) + +#define DECL_IMPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) == 1) +#define SET_DECL_IMPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) = 1) +#define CLASSTYPE_IMPLICIT_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE(NODE) == 1) +#define SET_CLASSTYPE_IMPLICIT_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE(NODE) = 1) + +#define DECL_EXPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) == 3) +#define SET_DECL_EXPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) = 3) +#define CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE(NODE) == 3) +#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \ + (CLASSTYPE_USE_TEMPLATE(NODE) = 3) + +/* Non-zero if DECL is a friend function which is an instantiation + from the point of view of the compiler, but not from the point of + view of the language. For example given: + template struct S { friend void f(T) {}; }; + the declaration of `void f(int)' generated when S is + instantiated will not be a DECL_TEMPLATE_INSTANTIATION, but will be + a DECL_FRIEND_PSUEDO_TEMPLATE_INSTANTIATION. */ +#define DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION(DECL) \ + (DECL_TEMPLATE_INFO (DECL) && !DECL_USE_TEMPLATE (DECL)) + +/* Non-zero if TYPE is a partial instantiation of a template class, + i.e., an instantiation whose instantiation arguments involve + template types. */ +#define PARTIAL_INSTANTIATION_P(TYPE) \ + (TYPE_LANG_SPECIFIC (TYPE)->type_flags.is_partial_instantiation) + +/* Non-zero iff we are currently processing a declaration for an + entity with its own template parameter list, and which is not a + full specialization. */ +#define PROCESSING_REAL_TEMPLATE_DECL_P() \ + (processing_template_decl > template_class_depth (current_class_type)) + +/* This function may be a guiding decl for a template. */ +#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE) + +/* Nonzero if this VAR_DECL or FUNCTION_DECL has already been + instantiated, i.e. its definition has been generated from the + pattern given in the the template. */ +#define DECL_TEMPLATE_INSTANTIATED(NODE) DECL_LANG_FLAG_1(NODE) + +/* We know what we're doing with this decl now. */ +#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE) + +/* This function was declared inline. This flag controls the linkage + semantics of 'inline'; whether or not the function is inlined is + controlled by DECL_INLINE. */ +#define DECL_THIS_INLINE(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_inline) + +/* DECL_EXTERNAL must be set on a decl until the decl is actually emitted, + so that assemble_external will work properly. So we have this flag to + tell us whether the decl is really not external. */ +#define DECL_NOT_REALLY_EXTERN(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern) + +#define DECL_REALLY_EXTERN(NODE) \ + (DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE)) + +#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i) + +/* ...and for unexpanded-parameterized-type nodes. */ +#define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE)) +#define UPT_PARMS(NODE) TREE_VALUE(TYPE_VALUES(NODE)) + +/* An un-parsed default argument looks like an identifier. */ +#define DEFARG_NODE_CHECK(t) TREE_CHECK(t, DEFAULT_ARG) +#define DEFARG_LENGTH(NODE) (DEFARG_NODE_CHECK(NODE)->identifier.length) +#define DEFARG_POINTER(NODE) (DEFARG_NODE_CHECK(NODE)->identifier.pointer) + +#define builtin_function(NAME, TYPE, CODE, LIBNAME) \ + define_function (NAME, TYPE, CODE, (void (*) PROTO((tree)))pushdecl, LIBNAME) + +/* These macros provide convenient access to the various _STMT nodes + created when parsing template declarations. */ +#define IF_COND(NODE) TREE_OPERAND (NODE, 0) +#define THEN_CLAUSE(NODE) TREE_OPERAND (NODE, 1) +#define ELSE_CLAUSE(NODE) TREE_OPERAND (NODE, 2) +#define WHILE_COND(NODE) TREE_OPERAND (NODE, 0) +#define WHILE_BODY(NODE) TREE_OPERAND (NODE, 1) +#define DO_COND(NODE) TREE_OPERAND (NODE, 0) +#define DO_BODY(NODE) TREE_OPERAND (NODE, 1) +#define RETURN_EXPR(NODE) TREE_OPERAND (NODE, 0) +#define EXPR_STMT_EXPR(NODE) TREE_OPERAND (NODE, 0) +#define FOR_INIT_STMT(NODE) TREE_OPERAND (NODE, 0) +#define FOR_COND(NODE) TREE_OPERAND (NODE, 1) +#define FOR_EXPR(NODE) TREE_OPERAND (NODE, 2) +#define FOR_BODY(NODE) TREE_OPERAND (NODE, 3) +#define SWITCH_COND(NODE) TREE_OPERAND (NODE, 0) +#define SWITCH_BODY(NODE) TREE_OPERAND (NODE, 1) +#define CASE_LOW(NODE) TREE_OPERAND (NODE, 0) +#define CASE_HIGH(NODE) TREE_OPERAND (NODE, 1) +#define GOTO_DESTINATION(NODE) TREE_OPERAND (NODE, 0) +#define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0) +#define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1) +#define HANDLER_PARMS(NODE) TREE_OPERAND (NODE, 0) +#define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1) +#define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0) +#define ASM_CV_QUAL(NODE) TREE_OPERAND (NODE, 0) +#define ASM_STRING(NODE) TREE_OPERAND (NODE, 1) +#define ASM_OUTPUTS(NODE) TREE_OPERAND (NODE, 2) +#define ASM_INPUTS(NODE) TREE_OPERAND (NODE, 3) +#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4) + +/* An enumeration of the kind of tags that C++ accepts. */ +enum tag_types { record_type, class_type, union_type, enum_type, + signature_type }; + +/* Zero means prototype weakly, as in ANSI C (no args means nothing). + Each language context defines how this variable should be set. */ +extern int strict_prototype; +extern int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus; + +/* Non-zero means that if a label exists, and no other identifier + applies, use the value of the label. */ +extern int flag_labels_ok; + +/* Non-zero means to collect statistics which might be expensive + and to print them when we are done. */ +extern int flag_detailed_statistics; + +/* Non-zero means warn in function declared in derived class has the + same name as a virtual in the base class, but fails to match the + type signature of any virtual function in the base class. */ +extern int warn_overloaded_virtual; + +/* Nonzero means warn about use of multicharacter literals. */ +extern int warn_multichar; + +/* Non-zero means warn if a non-templatized friend function is + declared in a templatized class. This behavior is warned about with + flag_guiding_decls in do_friend. */ +extern int warn_nontemplate_friend; + +/* in c-common.c */ +extern void declare_function_name PROTO((void)); +extern void decl_attributes PROTO((tree, tree, tree)); +extern void init_function_format_info PROTO((void)); +extern void record_function_format PROTO((tree, tree, int, int, int)); +extern void check_function_format PROTO((tree, tree, tree)); +/* Print an error message for invalid operands to arith operation CODE. + NOP_EXPR is used as a special case (see truthvalue_conversion). */ +extern void binary_op_error PROTO((enum tree_code)); +extern tree cp_build_qualified_type PROTO((tree, int)); +extern tree canonical_type_variant PROTO((tree)); +extern void c_expand_expr_stmt PROTO((tree)); +/* Validate the expression after `case' and apply default promotions. */ +extern tree check_case_value PROTO((tree)); +/* Concatenate a list of STRING_CST nodes into one STRING_CST. */ +extern tree combine_strings PROTO((tree)); +extern void constant_expression_warning PROTO((tree)); +extern tree convert_and_check PROTO((tree, tree)); +extern void overflow_warning PROTO((tree)); +extern void unsigned_conversion_warning PROTO((tree, tree)); +extern void c_apply_type_quals_to_decl PROTO((int, tree)); + +/* Read the rest of the current #-directive line. */ +#if USE_CPPLIB +extern char *get_directive_line PROTO((void)); +#define GET_DIRECTIVE_LINE() get_directive_line () +#else +extern char *get_directive_line PROTO((FILE *)); +#define GET_DIRECTIVE_LINE() get_directive_line (finput) +#endif +/* Subroutine of build_binary_op, used for comparison operations. + See if the operands have both been converted from subword integer types + and, if so, perhaps change them both back to their original type. */ +extern tree shorten_compare PROTO((tree *, tree *, tree *, enum tree_code *)); +/* Prepare expr to be an argument of a TRUTH_NOT_EXPR, + or validate its data type for an `if' or `while' statement or ?..: exp. */ +extern tree truthvalue_conversion PROTO((tree)); +extern tree type_for_mode PROTO((enum machine_mode, int)); +extern tree type_for_size PROTO((unsigned, int)); +extern int c_get_alias_set PROTO((tree)); + +/* in decl{2}.c */ +extern tree void_list_node; +extern tree void_zero_node; +extern tree default_function_type; +extern tree vtable_entry_type; +extern tree sigtable_entry_type; +extern tree __t_desc_type_node; +#if 0 +extern tree __tp_desc_type_node; +#endif +extern tree __access_mode_type_node; +extern tree __bltn_desc_type_node, __user_desc_type_node; +extern tree __class_desc_type_node, __attr_desc_type_node; +extern tree __ptr_desc_type_node, __func_desc_type_node; +extern tree __ptmf_desc_type_node, __ptmd_desc_type_node; +extern tree type_info_type_node; +extern tree class_star_type_node; +extern tree this_identifier; +extern tree ctor_identifier, dtor_identifier; +extern tree pfn_identifier; +extern tree index_identifier; +extern tree delta_identifier; +extern tree delta2_identifier; +extern tree pfn_or_delta2_identifier; +extern tree tag_identifier; +extern tree vt_off_identifier; +extern tree in_charge_identifier; + +/* A node that is a list (length 1) of error_mark_nodes. */ +extern tree error_mark_list; + +extern tree ptr_type_node; +extern tree class_type_node, record_type_node, union_type_node, enum_type_node; +extern tree unknown_type_node; +extern tree opaque_type_node, signature_type_node; + +extern tree vlist_identifier, vlist_type_node, vlist_zero_node; + +/* Node for "pointer to (virtual) function". + This may be distinct from ptr_type_node so gdb can distinguish them. */ +#define vfunc_ptr_type_node \ + (flag_vtable_thunks ? vtable_entry_type : ptr_type_node) + +/* The type of a vtbl, i.e., an array of vtable entries. */ +extern tree vtbl_type_node; +/* The type of a class vtbl pointer, i.e., a pointer to a vtable entry. */ +extern tree vtbl_ptr_type_node; +extern tree delta_type_node; +extern tree std_node; + +extern tree long_long_integer_type_node, long_long_unsigned_type_node; +/* For building calls to `delete'. */ +extern tree integer_two_node, integer_three_node; +extern tree boolean_type_node, boolean_true_node, boolean_false_node; + +extern tree null_node; + +extern tree anonymous_namespace_name; + +/* The FUNCTION_DECL for the default `::operator delete'. */ + +extern tree global_delete_fndecl; + +/* in pt.c */ + +/* These values are used for the `STRICT' parameter to type_unfication and + fn_type_unification. Their meanings are described with the + documentation for fn_type_unification. */ + +typedef enum unification_kind_t { + DEDUCE_CALL, + DEDUCE_CONV, + DEDUCE_EXACT +} unification_kind_t; + +extern tree current_template_parms; +extern HOST_WIDE_INT processing_template_decl; +extern tree last_tree; + +/* The template currently being instantiated, and where the instantiation + was triggered. */ +struct tinst_level +{ + tree decl; + int line; + char *file; + struct tinst_level *next; +}; + +extern int minimal_parse_mode; + +extern void maybe_print_template_context PROTO ((void)); + +/* in class.c */ + +/* When parsing a class definition, the access specifier most recently + given by the user, or, if no access specifier was given, the + default value appropriate for the kind of class (i.e., struct, + class, or union). */ +extern tree current_access_specifier; + +extern tree current_class_name; +extern tree current_class_type; +extern tree current_class_ptr; +extern tree previous_class_type; +extern tree current_class_ref; +extern int current_class_depth; + +extern tree current_lang_name; +extern tree lang_name_cplusplus, lang_name_c, lang_name_java; + +/* The low-water mark on the class-cache obstack. */ +extern char *class_cache_firstobj; + +/* Points to the name of that function. May not be the DECL_NAME + of CURRENT_FUNCTION_DECL due to overloading */ +extern tree original_function_name; + +/* in init.c */ +extern tree global_base_init_list; +extern tree current_base_init_list, current_member_init_list; + +extern int current_function_just_assigned_this; +extern int current_function_parms_stored; + +/* Here's where we control how name mangling takes place. */ + +#define OPERATOR_ASSIGN_FORMAT "__a%s" +#define OPERATOR_FORMAT "__%s" +#define OPERATOR_TYPENAME_FORMAT "__op" + +/* Cannot use '$' up front, because this confuses gdb + (names beginning with '$' are gdb-local identifiers). + + Note that all forms in which the '$' is significant are long enough + for direct indexing (meaning that if we know there is a '$' + at a particular location, we can index into the string at + any other location that provides distinguishing characters). */ + +/* Define NO_DOLLAR_IN_LABEL in your favorite tm file if your assembler + doesn't allow '$' in symbol names. */ +#ifndef NO_DOLLAR_IN_LABEL + +#define JOINER '$' + +#define VPTR_NAME "$v" +#define THROW_NAME "$eh_throw" +#define DESTRUCTOR_DECL_PREFIX "_$_" +#define AUTO_VTABLE_NAME "__vtbl$me__" +#define AUTO_TEMP_NAME "_$tmp_" +#define AUTO_TEMP_FORMAT "_$tmp_%d" +#define VTABLE_BASE "$vb" +#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt$%s") +#define VCTABLE_NAME "__vc$" +#define VLIST_NAME_FORMAT "__vl$%s" +#define VFIELD_BASE "$vf" +#define VFIELD_NAME "_vptr$" +#define VFIELD_NAME_FORMAT "_vptr$%s" +#define VBASE_NAME "_vb$" +#define VBASE_NAME_FORMAT "_vb$%s" +#define STATIC_NAME_FORMAT "_%s$%s" +#define ANON_AGGRNAME_FORMAT "$_%d" + +#else /* NO_DOLLAR_IN_LABEL */ + +#ifndef NO_DOT_IN_LABEL + +#define JOINER '.' + +#define VPTR_NAME ".v" +#define THROW_NAME ".eh_throw" +#define DESTRUCTOR_DECL_PREFIX "_._" +#define AUTO_VTABLE_NAME "__vtbl.me__" +#define AUTO_TEMP_NAME "_.tmp_" +#define AUTO_TEMP_FORMAT "_.tmp_%d" +#define VTABLE_BASE ".vb" +#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt.%s") +#define VCTABLE_NAME "__vc." +#define VLIST_NAME_FORMAT "__vl.%s" +#define VFIELD_BASE ".vf" +#define VFIELD_NAME "_vptr." +#define VFIELD_NAME_FORMAT "_vptr.%s" +#define VBASE_NAME "_vb." +#define VBASE_NAME_FORMAT "_vb.%s" +#define STATIC_NAME_FORMAT "_%s.%s" + +#define ANON_AGGRNAME_FORMAT "._%d" + +#else /* NO_DOT_IN_LABEL */ + +#define VPTR_NAME "__vptr" +#define VPTR_NAME_P(ID_NODE) \ + (!strncmp (IDENTIFIER_POINTER (ID_NODE), VPTR_NAME, sizeof (VPTR_NAME) - 1)) +#define THROW_NAME "__eh_throw" +#define DESTRUCTOR_DECL_PREFIX "__destr_" +#define DESTRUCTOR_NAME_P(ID_NODE) \ + (!strncmp (IDENTIFIER_POINTER (ID_NODE), DESTRUCTOR_DECL_PREFIX, \ + sizeof (DESTRUCTOR_DECL_PREFIX) - 1)) +#define IN_CHARGE_NAME "__in_chrg" +#define AUTO_VTABLE_NAME "__vtbl_me__" +#define AUTO_TEMP_NAME "__tmp_" +#define TEMP_NAME_P(ID_NODE) \ + (!strncmp (IDENTIFIER_POINTER (ID_NODE), AUTO_TEMP_NAME, \ + sizeof (AUTO_TEMP_NAME) - 1)) +#define AUTO_TEMP_FORMAT "__tmp_%d" +#define VTABLE_BASE "__vtb" +#define VTABLE_NAME "__vt_" +#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt_%s") +#define VTABLE_NAME_P(ID_NODE) \ + (!strncmp (IDENTIFIER_POINTER (ID_NODE), VTABLE_NAME, \ + sizeof (VTABLE_NAME) - 1)) +#define VCTABLE_NAME "__vc_" +#define VLIST_NAME_FORMAT "__vl_%s" +#define VFIELD_BASE "__vfb" +#define VFIELD_NAME "__vptr_" +#define VFIELD_NAME_P(ID_NODE) \ + (!strncmp (IDENTIFIER_POINTER (ID_NODE), VFIELD_NAME, \ + sizeof (VFIELD_NAME) - 1)) +#define VFIELD_NAME_FORMAT "_vptr_%s" +#define VBASE_NAME "__vb_" +#define VBASE_NAME_P(ID_NODE) \ + (!strncmp (IDENTIFIER_POINTER (ID_NODE), VBASE_NAME, \ + sizeof (VBASE_NAME) - 1)) +#define VBASE_NAME_FORMAT "__vb_%s" +#define STATIC_NAME_FORMAT "__static_%s_%s" + +#define ANON_AGGRNAME_PREFIX "__anon_" +#define ANON_AGGRNAME_P(ID_NODE) \ + (!strncmp (IDENTIFIER_POINTER (ID_NODE), ANON_AGGRNAME_PREFIX, \ + sizeof (ANON_AGGRNAME_PREFIX) - 1)) +#define ANON_AGGRNAME_FORMAT "__anon_%d" +#define ANON_PARMNAME_FORMAT "__%d" +#define ANON_PARMNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \ + && IDENTIFIER_POINTER (ID_NODE)[1] == '_' \ + && IDENTIFIER_POINTER (ID_NODE)[2] <= '9') + +#endif /* NO_DOT_IN_LABEL */ +#endif /* NO_DOLLAR_IN_LABEL */ + +#define THIS_NAME "this" +#define DESTRUCTOR_NAME_FORMAT "~%s" +#define FILE_FUNCTION_PREFIX_LEN 9 +#define CTOR_NAME "__ct" +#define DTOR_NAME "__dt" + +#define IN_CHARGE_NAME "__in_chrg" +#define VLIST_NAME "__vlist" +#define VLIST1_NAME "__vlist1" +#define VLIST_TYPE_NAME "6_Vlist" + +#define VTBL_PTR_TYPE "__vtbl_ptr_type" +#define VTABLE_DELTA_NAME "__delta" +#define VTABLE_INDEX_NAME "__index" +#define VTABLE_PFN_NAME "__pfn" +#define VTABLE_DELTA2_NAME "__delta2" + +#define SIGNATURE_FIELD_NAME "__s_" +#define SIGNATURE_FIELD_NAME_FORMAT "__s_%s" +#define SIGNATURE_OPTR_NAME "__optr" +#define SIGNATURE_SPTR_NAME "__sptr" +#define SIGNATURE_POINTER_NAME "__sp_" +#define SIGNATURE_POINTER_NAME_FORMAT "__%s%s%ssp_%s" +#define SIGNATURE_REFERENCE_NAME "__sr_" +#define SIGNATURE_REFERENCE_NAME_FORMAT "__%s%s%ssr_%s" + +#define SIGTABLE_PTR_TYPE "__sigtbl_ptr_type" +#define SIGTABLE_NAME_FORMAT "__st_%s_%s" +#define SIGTABLE_NAME_FORMAT_LONG "__st_%s_%s_%d" +#define SIGTABLE_TAG_NAME "__tag" +#define SIGTABLE_VB_OFF_NAME "__vb_off" +#define SIGTABLE_VT_OFF_NAME "__vt_off" +#define EXCEPTION_CLEANUP_NAME "exception cleanup" + +#define THIS_NAME_P(ID_NODE) (strcmp(IDENTIFIER_POINTER (ID_NODE), "this") == 0) + +#if !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) + +#define VPTR_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == JOINER \ + && IDENTIFIER_POINTER (ID_NODE)[1] == 'v') +#define DESTRUCTOR_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[1] == JOINER \ + && IDENTIFIER_POINTER (ID_NODE)[2] == '_') + +#define VTABLE_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[1] == 'v' \ + && IDENTIFIER_POINTER (ID_NODE)[2] == 't' \ + && IDENTIFIER_POINTER (ID_NODE)[3] == JOINER) + +#define VBASE_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[1] == 'v' \ + && IDENTIFIER_POINTER (ID_NODE)[2] == 'b' \ + && IDENTIFIER_POINTER (ID_NODE)[3] == JOINER) + +#define TEMP_NAME_P(ID_NODE) (!strncmp (IDENTIFIER_POINTER (ID_NODE), AUTO_TEMP_NAME, sizeof (AUTO_TEMP_NAME)-1)) +#define VFIELD_NAME_P(ID_NODE) (!strncmp (IDENTIFIER_POINTER (ID_NODE), VFIELD_NAME, sizeof(VFIELD_NAME)-1)) + +/* For anonymous aggregate types, we need some sort of name to + hold on to. In practice, this should not appear, but it should + not be harmful if it does. */ +#define ANON_AGGRNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == JOINER \ + && IDENTIFIER_POINTER (ID_NODE)[1] == '_') +#define ANON_PARMNAME_FORMAT "_%d" +#define ANON_PARMNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \ + && IDENTIFIER_POINTER (ID_NODE)[1] <= '9') +#endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */ + +/* Store the vbase pointer field name for type TYPE into pointer BUF. */ +#define FORMAT_VBASE_NAME(BUF,TYPE) do { \ + char *wbuf = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (TYPE) \ + + sizeof (VBASE_NAME) + 1); \ + sprintf (wbuf, VBASE_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (TYPE)); \ + (BUF) = wbuf; \ +} while (0) + +/* Returns non-zero iff ID_NODE is an IDENTIFIER_NODE whose name is + `main'. */ +#define MAIN_NAME_P(ID_NODE) \ + (strcmp (IDENTIFIER_POINTER (ID_NODE), "main") == 0) + +/* Returns non-zero iff NODE is a declaration for the global function + `main'. */ +#define DECL_MAIN_P(NODE) \ + (TREE_CODE (NODE) == FUNCTION_DECL \ + && DECL_LANGUAGE (NODE) == lang_c \ + && DECL_NAME (NODE) != NULL_TREE \ + && MAIN_NAME_P (DECL_NAME (NODE))) + + +/* Define the sets of attributes that member functions and baseclasses + can have. These are sensible combinations of {public,private,protected} + cross {virtual,non-virtual}. */ + +/* in class.c. */ +extern tree access_default_node; /* 0 */ +extern tree access_public_node; /* 1 */ +extern tree access_protected_node; /* 2 */ +extern tree access_private_node; /* 3 */ +extern tree access_default_virtual_node; /* 4 */ +extern tree access_public_virtual_node; /* 5 */ +extern tree access_protected_virtual_node; /* 6 */ +extern tree access_private_virtual_node; /* 7 */ + +/* Things for handling inline functions. */ + +struct pending_inline +{ + struct pending_inline *next; /* pointer to next in chain */ + int lineno; /* line number we got the text from */ + char *filename; /* name of file we were processing */ + tree fndecl; /* FUNCTION_DECL that brought us here */ + int token; /* token we were scanning */ + int token_value; /* value of token we were scanning (YYSTYPE) */ + + char *buf; /* pointer to character stream */ + int len; /* length of stream */ + unsigned int can_free : 1; /* free this after we're done with it? */ + unsigned int deja_vu : 1; /* set iff we don't want to see it again. */ + unsigned int interface : 2; /* 0=interface 1=unknown 2=implementation */ +}; + +/* in method.c */ +extern struct pending_inline *pending_inlines; + +/* Positive values means that we cannot make optimizing assumptions about + `this'. Negative values means we know `this' to be of static type. */ + +extern int flag_this_is_variable; + +/* Nonzero means generate 'rtti' that give run-time type information. */ + +extern int flag_rtti; + +/* Nonzero means do emit exported implementations of functions even if + they can be inlined. */ + +extern int flag_implement_inlines; + +/* Nonzero means templates obey #pragma interface and implementation. */ + +extern int flag_external_templates; + +/* Nonzero means templates are emitted where they are instantiated. */ + +extern int flag_alt_external_templates; + +/* Nonzero means implicit template instantiations are emitted. */ + +extern int flag_implicit_templates; + +/* Nonzero if we want to emit defined symbols with common-like linkage as + weak symbols where possible, in order to conform to C++ semantics. + Otherwise, emit them as local symbols. */ + +extern int flag_weak; + +/* Nonzero to enable experimental ABI changes. */ + +extern int flag_new_abi; + +/* Nonzero to not ignore namespace std. */ + +extern int flag_honor_std; + +/* Nonzero if we're done parsing and into end-of-file activities. */ + +extern int at_eof; + +enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG }; + +/* The following two can be derived from the previous one */ +extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */ + +/* Some macros for char-based bitfields. */ +#define B_SET(a,x) (a[x>>3] |= (1 << (x&7))) +#define B_CLR(a,x) (a[x>>3] &= ~(1 << (x&7))) +#define B_TST(a,x) (a[x>>3] & (1 << (x&7))) + +/* These are uses as bits in flags passed to build_method_call + to control its error reporting behavior. + + LOOKUP_PROTECT means flag access violations. + LOOKUP_COMPLAIN mean complain if no suitable member function + matching the arguments is found. + LOOKUP_NORMAL is just a combination of these two. + LOOKUP_NONVIRTUAL means make a direct call to the member function found + LOOKUP_GLOBAL means search through the space of overloaded functions, + as well as the space of member functions. + LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already + in the parameter list. + LOOKUP_HAS_VLIST means that the "vlist" variable is already in + the parameter list. + LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried. + DIRECT_BIND means that if a temporary is created, it should be created so + that it lives as long as the current variable bindings; otherwise it + only lives until the end of the complete-expression. + LOOKUP_SPECULATIVELY means return NULL_TREE if we cannot find what we are + after. Note, LOOKUP_COMPLAIN is checked and error messages printed + before LOOKUP_SPECULATIVELY is checked. + LOOKUP_NO_CONVERSION means that user-defined conversions are not + permitted. Built-in conversions are permitted. + LOOKUP_DESTRUCTOR means explicit call to destructor. + LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references. + + These are used in global lookup to support elaborated types and + qualifiers. + + LOOKUP_PREFER_TYPES means not to accept objects, and possibly namespaces. + LOOKUP_PREFER_NAMESPACES means not to accept objects, and possibly types. + LOOKUP_PREFER_BOTH means class-or-namespace-name. + LOOKUP_TEMPLATES_EXPECTED means that class templates also count + as types. */ + +#define LOOKUP_PROTECT (1) +#define LOOKUP_COMPLAIN (2) +#define LOOKUP_NORMAL (3) +/* #define LOOKUP_UNUSED (4) */ +#define LOOKUP_NONVIRTUAL (8) +#define LOOKUP_GLOBAL (16) +#define LOOKUP_HAS_IN_CHARGE (32) +#define LOOKUP_SPECULATIVELY (64) +#define LOOKUP_ONLYCONVERTING (128) +#define DIRECT_BIND (256) +#define LOOKUP_NO_CONVERSION (512) +#define LOOKUP_DESTRUCTOR (512) +#define LOOKUP_NO_TEMP_BIND (1024) +#define LOOKUP_PREFER_TYPES (2048) +#define LOOKUP_PREFER_NAMESPACES (4096) +#define LOOKUP_PREFER_BOTH (6144) +#define LOOKUP_TEMPLATES_EXPECTED (8192) +#define LOOKUP_HAS_VLIST (16384) + +#define LOOKUP_NAMESPACES_ONLY(f) \ + (((f) & LOOKUP_PREFER_NAMESPACES) && !((f) & LOOKUP_PREFER_TYPES)) +#define LOOKUP_TYPES_ONLY(f) \ + (!((f) & LOOKUP_PREFER_NAMESPACES) && ((f) & LOOKUP_PREFER_TYPES)) +#define LOOKUP_QUALIFIERS_ONLY(f) ((f) & LOOKUP_PREFER_BOTH) + + +/* These flags are used by the conversion code. + CONV_IMPLICIT : Perform implicit conversions (standard and user-defined). + CONV_STATIC : Perform the explicit conversions for static_cast. + CONV_CONST : Perform the explicit conversions for const_cast. + CONV_REINTERPRET: Perform the explicit conversions for reinterpret_cast. + CONV_PRIVATE : Perform upcasts to private bases. + CONV_FORCE_TEMP : Require a new temporary when converting to the same + aggregate type. */ + +#define CONV_IMPLICIT 1 +#define CONV_STATIC 2 +#define CONV_CONST 4 +#define CONV_REINTERPRET 8 +#define CONV_PRIVATE 16 +/* #define CONV_NONCONVERTING 32 */ +#define CONV_FORCE_TEMP 64 +#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_FORCE_TEMP) +#define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ + | CONV_REINTERPRET) +#define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ + | CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP) + +/* Used by build_expr_type_conversion to indicate which types are + acceptable as arguments to the expression under consideration. */ + +#define WANT_INT 1 /* integer types, including bool */ +#define WANT_FLOAT 2 /* floating point types */ +#define WANT_ENUM 4 /* enumerated types */ +#define WANT_POINTER 8 /* pointer types */ +#define WANT_NULL 16 /* null pointer constant */ +#define WANT_ARITH (WANT_INT | WANT_FLOAT) + +/* Used with comptypes, and related functions, to guide type + comparison. */ + +#define COMPARE_STRICT 0 /* Just check if the types are the + same. */ +#define COMPARE_BASE 1 /* Check to see if the second type is + derived from the first, or if both + are pointers (or references) and + the types pointed to by the second + type is derived from the pointed to + by the first. */ +#define COMPARE_RELAXED 2 /* Like COMPARE_DERIVED, but in + reverse. Also treat enmeration + types as the same as integer types + of the same width. */ +#define COMPARE_REDECLARATION 4 /* The comparsion is being done when + another declaration of an existing + entity is seen. */ +#define COMPARE_NO_ATTRIBUTES 8 /* The comparison should ignore + extra-linguistic type attributes. */ + +/* Used with push_overloaded_decl. */ +#define PUSH_GLOBAL 0 /* Push the DECL into namespace scope, + regardless of the current scope. */ +#define PUSH_LOCAL 1 /* Push the DECL into the current + scope. */ +#define PUSH_USING 2 /* We are pushing this DECL as the + result of a using declaration. */ + +/* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual + sense of `same'. */ +#define same_type_p(type1, type2) \ + comptypes ((type1), (type2), COMPARE_STRICT) + +/* Returns nonzero iff TYPE1 and TYPE2 are the same type, or if TYPE2 + is derived from TYPE1, or if TYPE2 is a pointer (reference) to a + class derived from the type pointed to (referred to) by TYPE1. */ +#define same_or_base_type_p(type1, type2) \ + comptypes ((type1), (type2), COMPARE_BASE) + +/* These macros are used to access a TEMPLATE_PARM_INDEX. */ +#define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index) +#define TEMPLATE_PARM_LEVEL(NODE) (((template_parm_index*) NODE)->level) +#define TEMPLATE_PARM_DESCENDANTS(NODE) (TREE_CHAIN (NODE)) +#define TEMPLATE_PARM_ORIG_LEVEL(NODE) (((template_parm_index*) NODE)->orig_level) +#define TEMPLATE_PARM_DECL(NODE) (((template_parm_index*) NODE)->decl) + +/* These macros are for accessing the fields of TEMPLATE_TYPE_PARM + and TEMPLATE_TEMPLATE_PARM nodes. */ +#define TEMPLATE_TYPE_PARM_INDEX(NODE) (TYPE_FIELDS (NODE)) +#define TEMPLATE_TYPE_IDX(NODE) \ + (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE))) +#define TEMPLATE_TYPE_LEVEL(NODE) \ + (TEMPLATE_PARM_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE))) +#define TEMPLATE_TYPE_ORIG_LEVEL(NODE) \ + (TEMPLATE_PARM_ORIG_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE))) +#define TEMPLATE_TYPE_DECL(NODE) \ + (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE))) + +/* in lex.c */ +/* Indexed by TREE_CODE, these tables give C-looking names to + operators represented by TREE_CODES. For example, + opname_tab[(int) MINUS_EXPR] == "-". */ +extern char **opname_tab, **assignop_tab; + +/* in call.c */ +extern int check_dtor_name PROTO((tree, tree)); +extern int get_arglist_len_in_bytes PROTO((tree)); + +extern tree build_vfield_ref PROTO((tree, tree)); +extern tree resolve_scope_to_name PROTO((tree, tree)); +extern tree build_scoped_method_call PROTO((tree, tree, tree, tree)); +extern tree build_addr_func PROTO((tree)); +extern tree build_call PROTO((tree, tree, tree)); +extern tree build_method_call PROTO((tree, tree, tree, tree, int)); +extern int null_ptr_cst_p PROTO((tree)); +extern tree type_decays_to PROTO((tree)); +extern tree build_user_type_conversion PROTO((tree, tree, int)); +extern tree build_new_function_call PROTO((tree, tree)); +extern tree build_new_op PROTO((enum tree_code, int, tree, tree, tree)); +extern tree build_op_new_call PROTO((enum tree_code, tree, tree, int)); +extern tree build_op_delete_call PROTO((enum tree_code, tree, tree, int, tree)); +extern int can_convert PROTO((tree, tree)); +extern int can_convert_arg PROTO((tree, tree, tree)); +extern int enforce_access PROTO((tree, tree)); +extern tree convert_default_arg PROTO((tree, tree, tree)); +extern tree convert_arg_to_ellipsis PROTO((tree)); +extern int is_properly_derived_from PROTO((tree, tree)); + +/* in class.c */ +extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int)); +extern tree build_vtbl_ref PROTO((tree, tree)); +extern tree build_vfn_ref PROTO((tree *, tree, tree)); +extern void add_method PROTO((tree, tree *, tree)); +extern int currently_open_class PROTO((tree)); +extern tree get_vfield_offset PROTO((tree)); +extern void duplicate_tag_error PROTO((tree)); +extern tree finish_struct PROTO((tree, tree, int)); +extern void finish_struct_1 PROTO((tree, int)); +extern int resolves_to_fixed_type_p PROTO((tree, int *)); +extern void init_class_processing PROTO((void)); +extern int is_empty_class PROTO((tree)); +extern void pushclass PROTO((tree, int)); +extern void popclass PROTO((void)); +extern void push_nested_class PROTO((tree, int)); +extern void pop_nested_class PROTO((void)); +extern void push_lang_context PROTO((tree)); +extern void pop_lang_context PROTO((void)); +extern tree instantiate_type PROTO((tree, tree, int)); +extern void print_class_statistics PROTO((void)); +extern void push_cache_obstack PROTO((void)); +extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *, tree)); +extern void build_self_reference PROTO((void)); +extern void warn_hidden PROTO((tree)); +extern tree get_enclosing_class PROTO((tree)); +int is_base_of_enclosing_class PROTO((tree, tree)); +extern void unreverse_member_declarations PROTO((tree)); +extern void invalidate_class_lookup_cache PROTO((void)); +extern void maybe_note_name_used_in_class PROTO((tree, tree)); +extern void note_name_declared_in_class PROTO((tree, tree)); + +/* in cvt.c */ +extern tree convert_to_reference PROTO((tree, tree, int, int, tree)); +extern tree convert_from_reference PROTO((tree)); +extern tree convert_pointer_to_real PROTO((tree, tree)); +extern tree convert_pointer_to PROTO((tree, tree)); +extern tree ocp_convert PROTO((tree, tree, int, int)); +extern tree cp_convert PROTO((tree, tree)); +extern tree convert PROTO((tree, tree)); +extern tree convert_force PROTO((tree, tree, int)); +extern tree build_type_conversion PROTO((tree, tree, int)); +extern tree build_expr_type_conversion PROTO((int, tree, int)); +extern tree type_promotes_to PROTO((tree)); +extern tree perform_qualification_conversions PROTO((tree, tree)); + +/* decl.c */ +/* resume_binding_level */ +extern void set_identifier_local_value PROTO((tree, tree)); +extern int global_bindings_p PROTO((void)); +extern int toplevel_bindings_p PROTO((void)); +extern int namespace_bindings_p PROTO((void)); +extern void keep_next_level PROTO((void)); +extern int kept_level_p PROTO((void)); +extern void declare_parm_level PROTO((void)); +extern void declare_pseudo_global_level PROTO((void)); +extern int pseudo_global_level_p PROTO((void)); +extern void set_class_shadows PROTO((tree)); +extern void pushlevel PROTO((int)); +extern void note_level_for_for PROTO((void)); +extern void pushlevel_temporary PROTO((int)); +extern tree poplevel PROTO((int, int, int)); +extern void resume_level PROTO((struct binding_level *)); +extern void delete_block PROTO((tree)); +extern void insert_block PROTO((tree)); +extern void add_block_current_level PROTO((tree)); +extern void set_block PROTO((tree)); +extern void pushlevel_class PROTO((void)); +extern void print_binding_stack PROTO((void)); +extern void print_binding_level PROTO((struct binding_level *)); +extern void push_namespace PROTO((tree)); +extern void pop_namespace PROTO((void)); +extern void maybe_push_to_top_level PROTO((int)); +extern void push_to_top_level PROTO((void)); +extern void pop_from_top_level PROTO((void)); +extern tree identifier_type_value PROTO((tree)); +extern void set_identifier_type_value PROTO((tree, tree)); +extern void pop_everything PROTO((void)); +extern void pushtag PROTO((tree, tree, int)); +extern tree make_anon_name PROTO((void)); +extern void clear_anon_tags PROTO((void)); +extern int decls_match PROTO((tree, tree)); +extern int duplicate_decls PROTO((tree, tree)); +extern tree pushdecl PROTO((tree)); +extern tree pushdecl_top_level PROTO((tree)); +extern void pushdecl_class_level PROTO((tree)); +#if 0 +extern void pushdecl_nonclass_level PROTO((tree)); +#endif +extern tree pushdecl_namespace_level PROTO((tree)); +extern tree push_using_decl PROTO((tree, tree)); +extern tree push_using_directive PROTO((tree)); +extern void push_class_level_binding PROTO((tree, tree)); +extern tree implicitly_declare PROTO((tree)); +extern tree lookup_label PROTO((tree)); +extern tree shadow_label PROTO((tree)); +extern tree define_label PROTO((char *, int, tree)); +extern void push_switch PROTO((void)); +extern void pop_switch PROTO((void)); +extern void define_case_label PROTO((void)); +extern tree getdecls PROTO((void)); +extern tree gettags PROTO((void)); +#if 0 +extern void set_current_level_tags_transparency PROTO((int)); +#endif +extern tree binding_for_name PROTO((tree, tree)); +extern tree namespace_binding PROTO((tree, tree)); +extern void set_namespace_binding PROTO((tree, tree, tree)); +extern tree lookup_namespace_name PROTO((tree, tree)); +extern tree build_typename_type PROTO((tree, tree, tree, tree)); +extern tree make_typename_type PROTO((tree, tree)); +extern tree lookup_name_nonclass PROTO((tree)); +extern tree lookup_function_nonclass PROTO((tree, tree)); +extern tree lookup_name PROTO((tree, int)); +extern tree lookup_name_current_level PROTO((tree)); +extern tree lookup_type_current_level PROTO((tree)); +extern tree lookup_name_namespace_only PROTO((tree)); +extern void begin_only_namespace_names PROTO((void)); +extern void end_only_namespace_names PROTO((void)); +extern tree namespace_ancestor PROTO((tree, tree)); +extern int lookup_using_namespace PROTO((tree,tree,tree,tree,int)); +extern int qualified_lookup_using_namespace PROTO((tree,tree,tree,int)); +extern tree auto_function PROTO((tree, tree, enum built_in_function)); +extern void init_decl_processing PROTO((void)); +extern int init_type_desc PROTO((void)); +extern tree define_function + PROTO((const char *, tree, enum built_in_function, + void (*) (tree), const char *)); +extern tree check_tag_decl PROTO((tree)); +extern void shadow_tag PROTO((tree)); +extern tree groktypename PROTO((tree)); +extern tree start_decl PROTO((tree, tree, int, tree, tree)); +extern void start_decl_1 PROTO((tree)); +extern void cp_finish_decl PROTO((tree, tree, tree, int, int)); +extern void finish_decl PROTO((tree, tree, tree)); +extern void expand_static_init PROTO((tree, tree)); +extern int complete_array_type PROTO((tree, tree, int)); +extern tree build_ptrmemfunc_type PROTO((tree)); +/* the grokdeclarator prototype is in decl.h */ +extern int parmlist_is_exprlist PROTO((tree)); +extern int copy_args_p PROTO((tree)); +extern int grok_ctor_properties PROTO((tree, tree)); +extern void grok_op_properties PROTO((tree, int, int)); +extern tree xref_tag PROTO((tree, tree, int)); +extern tree xref_tag_from_type PROTO((tree, tree, int)); +extern void xref_basetypes PROTO((tree, tree, tree, tree)); +extern tree start_enum PROTO((tree)); +extern tree finish_enum PROTO((tree)); +extern tree build_enumerator PROTO((tree, tree, tree)); +extern int start_function PROTO((tree, tree, tree, int)); +extern void expand_start_early_try_stmts PROTO((void)); +extern void store_parm_decls PROTO((void)); +extern void store_return_init PROTO((tree, tree)); +extern void finish_function PROTO((int, int, int)); +extern tree start_method PROTO((tree, tree, tree)); +extern tree finish_method PROTO((tree)); +extern void hack_incomplete_structures PROTO((tree)); +extern tree maybe_build_cleanup_and_delete PROTO((tree)); +extern tree maybe_build_cleanup PROTO((tree)); +extern void cplus_expand_expr_stmt PROTO((tree)); +extern void finish_stmt PROTO((void)); +extern void push_cp_function_context PROTO((tree)); +extern void pop_cp_function_context PROTO((tree)); +extern int in_function_p PROTO((void)); +extern void replace_defarg PROTO((tree, tree)); +extern void print_other_binding_stack PROTO((struct binding_level *)); +extern void revert_static_member_fn PROTO((tree*, tree*, tree*)); +extern void fixup_anonymous_union PROTO((tree)); +extern int check_static_variable_definition PROTO((tree, tree)); +extern void push_local_binding PROTO((tree, tree, int)); +extern int push_class_binding PROTO((tree, tree)); +extern tree check_default_argument PROTO((tree, tree)); +extern tree push_overloaded_decl PROTO((tree, int)); +extern void clear_identifier_class_values PROTO((void)); +extern void storetags PROTO((tree)); +extern int vtable_decl_p PROTO((tree, void *)); +extern int vtype_decl_p PROTO((tree, void *)); +extern int sigtable_decl_p PROTO((tree, void *)); +typedef int (*walk_globals_pred) PROTO((tree, void *)); +typedef int (*walk_globals_fn) PROTO((tree *, void *)); +extern int walk_globals PROTO((walk_globals_pred, + walk_globals_fn, + void *)); +typedef int (*walk_namespaces_fn) PROTO((tree, void *)); +extern int walk_namespaces PROTO((walk_namespaces_fn, + void *)); +extern int wrapup_globals_for_namespace PROTO((tree, void *)); + +/* in decl2.c */ +extern int check_java_method PROTO((tree)); +extern int lang_decode_option PROTO((int, char **)); +extern tree grok_method_quals PROTO((tree, tree, tree)); +extern void warn_if_unknown_interface PROTO((tree)); +extern void grok_x_components PROTO((tree)); +extern void maybe_retrofit_in_chrg PROTO((tree)); +extern void maybe_make_one_only PROTO((tree)); +extern void grokclassfn PROTO((tree, tree, enum overload_flags, tree)); +extern tree grok_alignof PROTO((tree)); +extern tree grok_array_decl PROTO((tree, tree)); +extern tree delete_sanity PROTO((tree, tree, int, int)); +extern tree check_classfn PROTO((tree, tree)); +extern void check_member_template PROTO((tree)); +extern tree grokfield PROTO((tree, tree, tree, tree, tree)); +extern tree grokbitfield PROTO((tree, tree, tree)); +extern tree groktypefield PROTO((tree, tree)); +extern tree grokoptypename PROTO((tree, tree)); +extern int copy_assignment_arg_p PROTO((tree, int)); +extern void cplus_decl_attributes PROTO((tree, tree, tree)); +extern tree constructor_name_full PROTO((tree)); +extern tree constructor_name PROTO((tree)); +extern void setup_vtbl_ptr PROTO((void)); +extern void mark_inline_for_output PROTO((tree)); +extern void clear_temp_name PROTO((void)); +extern tree get_temp_name PROTO((tree, int)); +extern tree get_temp_regvar PROTO((tree, tree)); +extern void finish_anon_union PROTO((tree)); +extern tree finish_table PROTO((tree, tree, tree, int)); +extern void finish_builtin_type PROTO((tree, const char *, + tree *, int, tree)); +extern tree coerce_new_type PROTO((tree)); +extern tree coerce_delete_type PROTO((tree)); +extern void comdat_linkage PROTO((tree)); +extern void import_export_class PROTO((tree)); +extern void import_export_vtable PROTO((tree, tree, int)); +extern void import_export_decl PROTO((tree)); +extern tree build_cleanup PROTO((tree)); +extern void finish_file PROTO((void)); +extern tree reparse_absdcl_as_expr PROTO((tree, tree)); +extern tree reparse_absdcl_as_casts PROTO((tree, tree)); +extern tree build_expr_from_tree PROTO((tree)); +extern tree reparse_decl_as_expr PROTO((tree, tree)); +extern tree finish_decl_parsing PROTO((tree)); +extern tree check_cp_case_value PROTO((tree)); +extern void set_decl_namespace PROTO((tree, tree, int)); +extern tree current_decl_namespace PROTO((void)); +extern void push_decl_namespace PROTO((tree)); +extern void pop_decl_namespace PROTO((void)); +extern void push_scope PROTO((tree)); +extern void pop_scope PROTO((tree)); +extern void do_namespace_alias PROTO((tree, tree)); +extern void do_toplevel_using_decl PROTO((tree)); +extern void do_local_using_decl PROTO((tree)); +extern tree do_class_using_decl PROTO((tree)); +extern void do_using_directive PROTO((tree)); +extern void check_default_args PROTO((tree)); +extern void mark_used PROTO((tree)); +extern tree handle_class_head PROTO((tree, tree, tree)); +extern tree lookup_arg_dependent PROTO((tree, tree, tree)); +extern void finish_static_data_member_decl PROTO((tree, tree, tree, int, int)); + +/* in errfn.c */ +/* The cp_* functions aren't suitable for ATTRIBUTE_PRINTF. */ +extern void cp_error PVPROTO((const char *, ...)); +extern void cp_error_at PVPROTO((const char *, ...)); +extern void cp_warning PVPROTO((const char *, ...)); +extern void cp_warning_at PVPROTO((const char *, ...)); +extern void cp_pedwarn PVPROTO((const char *, ...)); +extern void cp_pedwarn_at PVPROTO((const char *, ...)); +extern void cp_compiler_error PVPROTO((const char *, ...)); +extern void cp_sprintf PVPROTO((const char *, ...)); +extern void cp_deprecated PROTO((const char*)); + +/* in error.c */ +extern void init_error PROTO((void)); +extern char *fndecl_as_string PROTO((tree, int)); +extern char *type_as_string PROTO((tree, int)); +extern char *type_as_string_real PROTO((tree, int, int)); +extern char *args_as_string PROTO((tree, int)); +extern char *decl_as_string PROTO((tree, int)); +extern char *expr_as_string PROTO((tree, int)); +extern char *code_as_string PROTO((enum tree_code, int)); +extern char *language_as_string PROTO((enum languages, int)); +extern char *parm_as_string PROTO((int, int)); +extern char *op_as_string PROTO((enum tree_code, int)); +extern char *assop_as_string PROTO((enum tree_code, int)); +extern char *cv_as_string PROTO((tree, int)); +extern char *lang_decl_name PROTO((tree, int)); +extern char *cp_file_of PROTO((tree)); +extern int cp_line_of PROTO((tree)); + +/* in except.c */ +extern void init_exception_processing PROTO((void)); +extern void expand_start_catch_block PROTO((tree, tree)); +extern void expand_end_catch_block PROTO((void)); +extern void expand_builtin_throw PROTO((void)); +extern void expand_start_eh_spec PROTO((void)); +extern void expand_exception_blocks PROTO((void)); +extern tree start_anon_func PROTO((void)); +extern void end_anon_func PROTO((void)); +extern void expand_throw PROTO((tree)); +extern tree build_throw PROTO((tree)); +extern void mark_all_runtime_matches PROTO((void)); + +/* in expr.c */ +extern void init_cplus_expand PROTO((void)); +extern void fixup_result_decl PROTO((tree, struct rtx_def *)); +extern int extract_init PROTO((tree, tree)); +extern void do_case PROTO((tree, tree)); + +/* friend.c */ +extern int is_friend PROTO((tree, tree)); +extern void make_friend_class PROTO((tree, tree)); +extern void add_friend PROTO((tree, tree)); +extern void add_friends PROTO((tree, tree, tree)); +extern tree do_friend PROTO((tree, tree, tree, tree, tree, enum overload_flags, tree, int)); + +/* in init.c */ +extern void init_init_processing PROTO((void)); +extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree)); +extern void emit_base_init PROTO((tree, int)); +extern void check_base_init PROTO((tree)); +extern void expand_member_init PROTO((tree, tree, tree)); +extern void expand_aggr_init PROTO((tree, tree, int)); +extern int is_aggr_typedef PROTO((tree, int)); +extern int is_aggr_type PROTO((tree, int)); +extern tree get_aggr_from_typedef PROTO((tree, int)); +extern tree get_type_value PROTO((tree)); +extern tree build_member_call PROTO((tree, tree, tree)); +extern tree build_offset_ref PROTO((tree, tree)); +extern tree resolve_offset_ref PROTO((tree)); +extern tree decl_constant_value PROTO((tree)); +extern tree build_new PROTO((tree, tree, tree, int)); +extern tree build_new_1 PROTO((tree)); +extern tree expand_vec_init PROTO((tree, tree, tree, tree, int)); +extern tree build_x_delete PROTO((tree, int, tree)); +extern tree build_delete PROTO((tree, tree, tree, int, int)); +extern tree build_vbase_delete PROTO((tree, tree)); +extern tree build_vec_delete PROTO((tree, tree, tree, tree, int)); +extern tree build_base_dtor_call PROTO((tree, tree, tree)); +extern void init_vlist PROTO((tree)); + +/* in input.c */ + +/* in lex.c */ +extern char *file_name_nondirectory PROTO((const char *)); +extern tree make_pointer_declarator PROTO((tree, tree)); +extern tree make_reference_declarator PROTO((tree, tree)); +extern tree make_call_declarator PROTO((tree, tree, tree, tree)); +extern void set_quals_and_spec PROTO((tree, tree, tree)); +extern char *operator_name_string PROTO((tree)); +extern void lang_init PROTO((void)); +extern void lang_finish PROTO((void)); +#if 0 +extern void reinit_lang_specific PROTO((void)); +#endif +extern void reinit_parse_for_function PROTO((void)); +extern void print_parse_statistics PROTO((void)); +extern void extract_interface_info PROTO((void)); +extern void do_pending_inlines PROTO((void)); +extern void process_next_inline PROTO((tree)); +extern struct pending_input *save_pending_input PROTO((void)); +extern void restore_pending_input PROTO((struct pending_input *)); +extern void yyungetc PROTO((int, int)); +extern void reinit_parse_for_method PROTO((int, tree)); +extern void reinit_parse_for_block PROTO((int, struct obstack *)); +extern tree cons_up_default_function PROTO((tree, tree, int)); +extern void check_for_missing_semicolon PROTO((tree)); +extern void note_got_semicolon PROTO((tree)); +extern void note_list_got_semicolon PROTO((tree)); +extern void do_pending_lang_change PROTO((void)); +extern int identifier_type PROTO((tree)); +extern void see_typename PROTO((void)); +extern tree do_identifier PROTO((tree, int, tree)); +extern tree do_scoped_id PROTO((tree, int)); +extern tree identifier_typedecl_value PROTO((tree)); +extern int real_yylex PROTO((void)); +extern int is_rid PROTO((tree)); +extern tree build_lang_decl PROTO((enum tree_code, tree, tree)); +extern void retrofit_lang_decl PROTO((tree)); +extern tree build_lang_field_decl PROTO((enum tree_code, tree, tree)); +extern void copy_lang_decl PROTO((tree)); +extern tree make_lang_type PROTO((enum tree_code)); +extern void dump_time_statistics PROTO((void)); +extern void compiler_error PVPROTO((const char *, ...)) + ATTRIBUTE_PRINTF_1; +extern void yyerror PROTO((const char *)); +extern void clear_inline_text_obstack PROTO((void)); +extern void maybe_snarf_defarg PROTO((void)); +extern tree snarf_defarg PROTO((void)); +extern void add_defarg_fn PROTO((tree)); +extern void do_pending_defargs PROTO((void)); +extern int identifier_type PROTO((tree)); +extern void yyhook PROTO((int)); +extern int cp_type_qual_from_rid PROTO((tree)); + +/* in method.c */ +extern void init_method PROTO((void)); +extern void do_inline_function_hair PROTO((tree, tree)); +extern char *build_overload_name PROTO((tree, int, int)); +extern tree build_static_name PROTO((tree, tree)); +extern tree build_decl_overload PROTO((tree, tree, int)); +extern tree build_decl_overload_real PROTO((tree, tree, tree, tree, + tree, int)); +extern void set_mangled_name_for_decl PROTO((tree)); +extern tree build_typename_overload PROTO((tree)); +extern tree build_overload_with_type PROTO((tree, tree)); +extern tree build_destructor_name PROTO((tree, int)); +extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree)); +extern tree hack_identifier PROTO((tree, tree)); +extern tree make_thunk PROTO((tree, int)); +extern void emit_thunk PROTO((tree)); +extern void synthesize_method PROTO((tree)); +extern tree get_id_2 PROTO((char *, tree)); +extern tree get_vlist_vtable_id PROTO((tree, tree)); + + +/* in pt.c */ +extern void check_template_shadow PROTO ((tree)); +extern tree innermost_args PROTO ((tree)); +extern tree tsubst PROTO ((tree, tree, int, tree)); +extern tree tsubst_expr PROTO ((tree, tree, int, tree)); +extern tree tsubst_copy PROTO ((tree, tree, int, tree)); +extern void maybe_begin_member_template_processing PROTO((tree)); +extern void maybe_end_member_template_processing PROTO((void)); +extern tree finish_member_template_decl PROTO((tree)); +extern void begin_template_parm_list PROTO((void)); +extern void begin_specialization PROTO((void)); +extern void reset_specialization PROTO((void)); +extern void end_specialization PROTO((void)); +extern void begin_explicit_instantiation PROTO((void)); +extern void end_explicit_instantiation PROTO((void)); +extern tree check_explicit_specialization PROTO((tree, tree, int, int)); +extern tree process_template_parm PROTO((tree, tree)); +extern tree end_template_parm_list PROTO((tree)); +extern void end_template_decl PROTO((void)); +extern tree current_template_args PROTO((void)); +extern tree push_template_decl PROTO((tree)); +extern tree push_template_decl_real PROTO((tree, int)); +extern void redeclare_class_template PROTO((tree, tree)); +extern tree lookup_template_class PROTO((tree, tree, tree, tree, int)); +extern tree lookup_template_function PROTO((tree, tree)); +extern int uses_template_parms PROTO((tree)); +extern tree instantiate_class_template PROTO((tree)); +extern tree instantiate_template PROTO((tree, tree)); +extern void overload_template_name PROTO((tree)); +extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t)); +struct tinst_level *tinst_for_decl PROTO((void)); +extern void mark_decl_instantiated PROTO((tree, int)); +extern int more_specialized PROTO((tree, tree, tree)); +extern void mark_class_instantiated PROTO((tree, int)); +extern void do_decl_instantiation PROTO((tree, tree, tree)); +extern void do_type_instantiation PROTO((tree, tree)); +extern tree instantiate_decl PROTO((tree)); +extern tree do_poplevel PROTO((void)); +extern tree get_bindings PROTO((tree, tree, tree)); +/* CONT ... */ +extern void add_tree PROTO((tree)); +extern void begin_tree PROTO((void)); +extern void end_tree PROTO((void)); +extern void add_maybe_template PROTO((tree, tree)); +extern void pop_tinst_level PROTO((void)); +extern int more_specialized_class PROTO((tree, tree)); +extern void do_pushlevel PROTO((void)); +extern int is_member_template PROTO((tree)); +extern int template_parms_equal PROTO((tree, tree)); +extern int comp_template_parms PROTO((tree, tree)); +extern int template_class_depth PROTO((tree)); +extern int is_specialization_of PROTO((tree, tree)); +extern int comp_template_args PROTO((tree, tree)); +extern void maybe_process_partial_specialization PROTO((tree)); +extern void maybe_check_template_type PROTO((tree)); +extern tree most_specialized_instantiation PROTO((tree, tree)); +extern void print_candidates PROTO((tree)); +extern int instantiate_pending_templates PROTO((void)); + +extern int processing_specialization; +extern int processing_explicit_instantiation; +extern int processing_template_parmlist; + +/* in repo.c */ +extern void repo_template_used PROTO((tree)); +extern void repo_template_instantiated PROTO((tree, int)); +extern void init_repo PROTO((const char *)); +extern void finish_repo PROTO((void)); + +/* in rtti.c */ +extern void init_rtti_processing PROTO((void)); +extern tree get_tinfo_fn_dynamic PROTO((tree)); +extern tree build_typeid PROTO((tree)); +extern tree build_x_typeid PROTO((tree)); +extern tree get_tinfo_fn PROTO((tree)); +extern tree get_tinfo_fn_unused PROTO((tree)); +extern tree get_typeid PROTO((tree)); +extern tree get_typeid_1 PROTO((tree)); +extern tree build_dynamic_cast PROTO((tree, tree)); +extern void synthesize_tinfo_fn PROTO((tree)); + +/* in search.c */ +extern int types_overlap_p PROTO((tree, tree)); +extern tree get_vbase PROTO((tree, tree)); +extern tree get_binfo PROTO((tree, tree, int)); +extern int get_base_distance PROTO((tree, tree, int, tree *)); +extern int accessible_p PROTO((tree, tree)); +extern tree lookup_field PROTO((tree, tree, int, int)); +extern int lookup_fnfields_1 PROTO((tree, tree)); +extern tree lookup_fnfields PROTO((tree, tree, int)); +extern tree lookup_member PROTO((tree, tree, int, int)); +extern tree lookup_nested_tag PROTO((tree, tree)); +extern tree get_matching_virtual PROTO((tree, tree, int)); +extern tree get_abstract_virtuals PROTO((tree)); +extern tree init_vbase_pointers PROTO((tree, tree)); +extern void expand_indirect_vtbls_init PROTO((tree, tree, tree)); +extern void clear_search_slots PROTO((tree)); +extern tree get_vbase_types PROTO((tree)); +extern void note_debug_info_needed PROTO((tree)); +extern void push_class_decls PROTO((tree)); +extern void pop_class_decls PROTO((void)); +extern void unuse_fields PROTO((tree)); +extern void print_search_statistics PROTO((void)); +extern void init_search_processing PROTO((void)); +extern void reinit_search_statistics PROTO((void)); +extern tree current_scope PROTO((void)); +extern tree lookup_conversions PROTO((tree)); +extern tree binfo_for_vtable PROTO((tree)); +extern tree dfs_walk PROTO((tree, + tree (*)(tree, void *), + tree (*) (tree, void *), + void *)); +extern tree dfs_unmark PROTO((tree, void *)); +extern tree markedp PROTO((tree, void *)); + +/* in semantics.c */ +extern void finish_expr_stmt PROTO((tree)); +extern tree begin_if_stmt PROTO((void)); +extern void finish_if_stmt_cond PROTO((tree, tree)); +extern tree finish_then_clause PROTO((tree)); +extern void begin_else_clause PROTO((void)); +extern void finish_else_clause PROTO((tree)); +extern void finish_if_stmt PROTO((void)); +extern tree begin_while_stmt PROTO((void)); +extern void finish_while_stmt_cond PROTO((tree, tree)); +extern void finish_while_stmt PROTO((tree)); +extern tree begin_do_stmt PROTO((void)); +extern void finish_do_body PROTO((tree)); +extern void finish_do_stmt PROTO((tree, tree)); +extern void finish_return_stmt PROTO((tree)); +extern tree begin_for_stmt PROTO((void)); +extern void finish_for_init_stmt PROTO((tree)); +extern void finish_for_cond PROTO((tree, tree)); +extern void finish_for_expr PROTO((tree, tree)); +extern void finish_for_stmt PROTO((tree, tree)); +extern void finish_break_stmt PROTO((void)); +extern void finish_continue_stmt PROTO((void)); +extern void begin_switch_stmt PROTO((void)); +extern tree finish_switch_cond PROTO((tree)); +extern void finish_switch_stmt PROTO((tree, tree)); +extern void finish_case_label PROTO((tree, tree)); +extern void finish_goto_stmt PROTO((tree)); +extern tree begin_try_block PROTO((void)); +extern void finish_try_block PROTO((tree)); +extern void finish_handler_sequence PROTO((tree)); +extern tree begin_handler PROTO((void)); +extern void finish_handler_parms PROTO((tree)); +extern void finish_handler PROTO((tree)); +extern tree begin_compound_stmt PROTO((int)); +extern tree finish_compound_stmt PROTO((int, tree)); +extern void finish_asm_stmt PROTO((tree, tree, tree, tree, tree)); +extern tree finish_parenthesized_expr PROTO((tree)); +extern tree begin_stmt_expr PROTO((void)); +extern tree finish_stmt_expr PROTO((tree, tree)); +extern tree finish_call_expr PROTO((tree, tree, int)); +extern tree finish_increment_expr PROTO((tree, enum tree_code)); +extern tree finish_this_expr PROTO((void)); +extern tree finish_object_call_expr PROTO((tree, tree, tree)); +extern tree finish_qualified_object_call_expr PROTO((tree, tree, tree)); +extern tree finish_pseudo_destructor_call_expr PROTO((tree, tree, tree)); +extern tree finish_qualified_call_expr PROTO ((tree, tree)); +extern tree finish_label_address_expr PROTO((tree)); +extern tree finish_unary_op_expr PROTO((enum tree_code, tree)); +extern tree finish_id_expr PROTO((tree)); +extern int begin_new_placement PROTO((void)); +extern tree finish_new_placement PROTO((tree, int)); +extern int begin_function_definition PROTO((tree, tree)); +extern tree begin_constructor_declarator PROTO((tree, tree)); +extern tree finish_declarator PROTO((tree, tree, tree, tree, int)); +extern void finish_translation_unit PROTO((void)); +extern tree finish_template_type_parm PROTO((tree, tree)); +extern tree finish_template_template_parm PROTO((tree, tree)); +extern tree finish_parmlist PROTO((tree, int)); +extern tree begin_class_definition PROTO((tree)); +extern tree finish_class_definition PROTO((tree, tree, int, int)); +extern void finish_default_args PROTO((void)); +extern void begin_inline_definitions PROTO((void)); +extern void finish_inline_definitions PROTO((void)); +extern tree finish_member_class_template PROTO((tree)); +extern void finish_template_decl PROTO((tree)); +extern tree finish_template_type PROTO((tree, tree, int)); +extern void enter_scope_of PROTO((tree)); +extern tree finish_base_specifier PROTO((tree, tree, int)); +extern void finish_member_declaration PROTO((tree)); +extern void check_multiple_declarators PROTO((void)); +extern tree finish_typeof PROTO((tree)); + +/* in sig.c */ +extern tree build_signature_pointer_type PROTO((tree)); +extern tree build_signature_reference_type PROTO((tree)); +extern tree build_signature_pointer_constructor PROTO((tree, tree)); +extern tree build_signature_method_call PROTO((tree, tree)); +extern tree build_optr_ref PROTO((tree)); +extern void append_signature_fields PROTO((tree)); + +/* in spew.c */ +extern void init_spew PROTO((void)); +extern int peekyylex PROTO((void)); +extern int yylex PROTO((void)); +extern tree arbitrate_lookup PROTO((tree, tree, tree)); + +/* in tree.c */ +extern int pod_type_p PROTO((tree)); +extern void unshare_base_binfos PROTO((tree)); +extern int member_p PROTO((tree)); +extern int real_lvalue_p PROTO((tree)); +extern tree build_min PVPROTO((enum tree_code, tree, ...)); +extern tree build_min_nt PVPROTO((enum tree_code, ...)); +extern tree min_tree_cons PROTO((tree, tree, tree)); +extern int lvalue_p PROTO((tree)); +extern int lvalue_or_else PROTO((tree, const char *)); +extern tree build_cplus_new PROTO((tree, tree)); +extern tree get_target_expr PROTO((tree)); +extern tree break_out_cleanups PROTO((tree)); +extern tree break_out_calls PROTO((tree)); +extern tree build_cplus_method_type PROTO((tree, tree, tree)); +extern tree build_cplus_staticfn_type PROTO((tree, tree, tree)); +extern tree build_cplus_array_type PROTO((tree, tree)); +extern int layout_basetypes PROTO((tree, int)); +extern tree build_vbase_pointer_fields PROTO((tree)); +extern tree build_base_fields PROTO((tree)); +extern tree hash_tree_cons PROTO((tree, tree, tree)); +extern tree hash_tree_chain PROTO((tree, tree)); +extern tree hash_chainon PROTO((tree, tree)); +extern tree make_binfo PROTO((tree, tree, tree, tree)); +extern tree binfo_value PROTO((tree, tree)); +extern tree reverse_path PROTO((tree)); +extern int count_functions PROTO((tree)); +extern int is_overloaded_fn PROTO((tree)); +extern tree get_first_fn PROTO((tree)); +extern tree binding_init PROTO((struct tree_binding*)); +extern int bound_pmf_p PROTO((tree)); +extern tree ovl_cons PROTO((tree, tree)); +extern tree scratch_ovl_cons PROTO((tree, tree)); +extern int ovl_member PROTO((tree, tree)); +extern tree build_overload PROTO((tree, tree)); +extern tree fnaddr_from_vtable_entry PROTO((tree)); +extern tree function_arg_chain PROTO((tree)); +extern int promotes_to_aggr_type PROTO((tree, enum tree_code)); +extern int is_aggr_type_2 PROTO((tree, tree)); +extern char *lang_printable_name PROTO((tree, int)); +extern tree build_exception_variant PROTO((tree, tree)); +extern tree copy_template_template_parm PROTO((tree)); +extern tree copy_to_permanent PROTO((tree)); +extern tree permanent_p PROTO((tree)); +extern void print_lang_statistics PROTO((void)); +extern void __eprintf + PROTO((const char *, const char *, unsigned, const char *)); +extern tree array_type_nelts_total PROTO((tree)); +extern tree array_type_nelts_top PROTO((tree)); +extern tree break_out_target_exprs PROTO((tree)); +extern tree get_type_decl PROTO((tree)); +extern tree vec_binfo_member PROTO((tree, tree)); +extern tree hack_decl_function_context PROTO((tree)); +extern tree decl_namespace_context PROTO((tree)); +extern tree lvalue_type PROTO((tree)); +extern tree error_type PROTO((tree)); +extern tree make_temp_vec PROTO((int)); +extern tree build_ptr_wrapper PROTO((void *)); +extern tree build_expr_ptr_wrapper PROTO((void *)); +extern tree build_int_wrapper PROTO((int)); +extern tree build_srcloc_here PROTO((void)); +extern int varargs_function_p PROTO((tree)); +extern int really_overloaded_fn PROTO((tree)); +extern int cp_tree_equal PROTO((tree, tree)); +extern int can_free PROTO((struct obstack *, tree)); +extern tree mapcar PROTO((tree, tree (*) (tree))); +extern tree no_linkage_check PROTO((tree)); +extern void debug_binfo PROTO((tree)); +extern void push_expression_obstack PROTO((void)); +extern tree build_dummy_object PROTO((tree)); +extern tree maybe_dummy_object PROTO((tree, tree *)); +extern int is_dummy_object PROTO((tree)); +extern tree search_tree PROTO((tree, tree (*)(tree))); +extern int cp_valid_lang_attribute PROTO((tree, tree, tree, tree)); +extern tree make_ptrmem_cst PROTO((tree, tree)); + +#define scratchalloc expralloc +#define scratch_tree_cons expr_tree_cons +#define build_scratch_list build_expr_list +#define make_scratch_vec make_temp_vec +#define push_scratch_obstack push_expression_obstack + +/* in typeck.c */ +extern int string_conv_p PROTO((tree, tree, int)); +extern tree condition_conversion PROTO((tree)); +extern tree target_type PROTO((tree)); +extern tree require_complete_type PROTO((tree)); +extern tree require_complete_type_in_void PROTO((tree)); +extern tree complete_type PROTO((tree)); +extern tree complete_type_or_else PROTO((tree, tree)); +extern int type_unknown_p PROTO((tree)); +extern int fntype_p PROTO((tree)); +extern tree commonparms PROTO((tree, tree)); +extern tree original_type PROTO((tree)); +extern tree common_type PROTO((tree, tree)); +extern int compexcepttypes PROTO((tree, tree)); +extern int comptypes PROTO((tree, tree, int)); +extern int comp_target_types PROTO((tree, tree, int)); +extern int compparms PROTO((tree, tree)); +extern int comp_target_types PROTO((tree, tree, int)); +extern int comp_cv_qualification PROTO((tree, tree)); +extern int comp_cv_qual_signature PROTO((tree, tree)); +extern int self_promoting_args_p PROTO((tree)); +extern tree unsigned_type PROTO((tree)); +extern tree signed_type PROTO((tree)); +extern tree signed_or_unsigned_type PROTO((int, tree)); +extern tree expr_sizeof PROTO((tree)); +extern tree c_sizeof PROTO((tree)); +extern tree c_sizeof_nowarn PROTO((tree)); +extern tree c_alignof PROTO((tree)); +extern tree inline_conversion PROTO((tree)); +extern tree decay_conversion PROTO((tree)); +extern tree default_conversion PROTO((tree)); +extern tree build_object_ref PROTO((tree, tree, tree)); +extern tree build_component_ref_1 PROTO((tree, tree, int)); +extern tree build_component_ref PROTO((tree, tree, tree, int)); +extern tree build_x_component_ref PROTO((tree, tree, tree, int)); +extern tree build_x_indirect_ref PROTO((tree, const char *)); +extern tree build_indirect_ref PROTO((tree, const char *)); +extern tree build_array_ref PROTO((tree, tree)); +extern tree build_x_function_call PROTO((tree, tree, tree)); +extern tree get_member_function_from_ptrfunc PROTO((tree *, tree)); +extern tree build_function_call_real PROTO((tree, tree, int, int)); +extern tree build_function_call PROTO((tree, tree)); +extern tree build_function_call_maybe PROTO((tree, tree)); +extern tree convert_arguments PROTO((tree, tree, tree, int)); +extern tree build_x_binary_op PROTO((enum tree_code, tree, tree)); +extern tree build_binary_op PROTO((enum tree_code, tree, tree)); +extern tree build_binary_op_nodefault PROTO((enum tree_code, tree, tree, enum tree_code)); +extern tree build_x_unary_op PROTO((enum tree_code, tree)); +extern tree build_unary_op PROTO((enum tree_code, tree, int)); +extern tree unary_complex_lvalue PROTO((enum tree_code, tree)); +extern int mark_addressable PROTO((tree)); +extern tree build_x_conditional_expr PROTO((tree, tree, tree)); +extern tree build_conditional_expr PROTO((tree, tree, tree)); +extern tree build_x_compound_expr PROTO((tree)); +extern tree build_compound_expr PROTO((tree)); +extern tree build_static_cast PROTO((tree, tree)); +extern tree build_reinterpret_cast PROTO((tree, tree)); +extern tree build_const_cast PROTO((tree, tree)); +extern tree build_c_cast PROTO((tree, tree)); +extern tree build_x_modify_expr PROTO((tree, enum tree_code, tree)); +extern tree build_modify_expr PROTO((tree, enum tree_code, tree)); +extern tree convert_for_initialization PROTO((tree, tree, tree, int, const char *, tree, int)); +extern void c_expand_asm_operands PROTO((tree, tree, tree, tree, int, char *, int)); +extern void c_expand_return PROTO((tree)); +extern tree c_expand_start_case PROTO((tree)); +extern int comp_ptr_ttypes PROTO((tree, tree)); +extern int ptr_reasonably_similar PROTO((tree, tree)); +extern tree build_ptrmemfunc PROTO((tree, tree, int)); +extern int cp_type_quals PROTO((tree)); +extern int cp_has_mutable_p PROTO((tree)); +extern int at_least_as_qualified_p PROTO((tree, tree)); +extern int more_qualified_p PROTO((tree, tree)); +extern tree build_ptrmemfunc1 PROTO((tree, tree, tree, tree, tree)); +extern void expand_ptrmemfunc_cst PROTO((tree, tree *, tree *, tree *, tree *)); +extern tree delta2_from_ptrmemfunc PROTO((tree)); +extern tree pfn_from_ptrmemfunc PROTO((tree)); + +/* in typeck2.c */ +extern tree error_not_base_type PROTO((tree, tree)); +extern tree binfo_or_else PROTO((tree, tree)); +extern void readonly_error PROTO((tree, const char *, int)); +extern void abstract_virtuals_error PROTO((tree, tree)); +extern void signature_error PROTO((tree, tree)); +extern void incomplete_type_error PROTO((tree, tree)); +extern void my_friendly_abort PROTO((int)) + ATTRIBUTE_NORETURN; +extern void my_friendly_assert PROTO((int, int)); +extern tree store_init_value PROTO((tree, tree)); +extern tree digest_init PROTO((tree, tree, tree *)); +extern tree build_scoped_ref PROTO((tree, tree)); +extern tree build_x_arrow PROTO((tree)); +extern tree build_m_component_ref PROTO((tree, tree)); +extern tree build_functional_cast PROTO((tree, tree)); +extern char *enum_name_string PROTO((tree, tree)); +extern void report_case_error PROTO((int, tree, tree, tree)); +extern void check_for_new_type PROTO((const char *, flagged_type_tree)); +extern tree initializer_constant_valid_p PROTO((tree, tree)); + +/* in xref.c */ +extern void GNU_xref_begin PROTO((const char *)); +extern void GNU_xref_end PROTO((int)); +extern void GNU_xref_file PROTO((const char *)); +extern void GNU_xref_start_scope PROTO((HOST_WIDE_INT)); +extern void GNU_xref_end_scope PROTO((HOST_WIDE_INT, HOST_WIDE_INT, int, int)); +extern void GNU_xref_ref PROTO((tree, const char *)); +extern void GNU_xref_decl PROTO((tree, tree)); +extern void GNU_xref_call PROTO((tree, const char *)); +extern void GNU_xref_function PROTO((tree, tree)); +extern void GNU_xref_assign PROTO((tree)); +extern void GNU_xref_hier PROTO((tree, tree, int, int, int)); +extern void GNU_xref_member PROTO((tree, tree)); + +/* -- end of C++ */ + +#endif /* not _CP_TREE_H */ Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/cp-tree.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/decl.c =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/decl.c (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/decl.c (revision 60969) @@ -0,0 +1,15160 @@ +/* Process declarations and variables for C compiler. + Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@cygnus.com) + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +/* Process declarations and symbol lookup for C front end. + Also constructs types; the standard scalar types at initialization, + and structure, union, array and enum types when they are declared. */ + +/* ??? not all decl nodes are given the most useful possible + line numbers. For example, the CONST_DECLs for enum values. */ + +#include "config.h" +#include "system.h" +#include "tree.h" +#include "rtl.h" +#include "flags.h" +#include "cp-tree.h" +#include "decl.h" +#include "lex.h" +#include +#include "obstack.h" +#include "defaults.h" +#include "output.h" +#include "except.h" +#include "toplev.h" +#include "../hash.h" + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +extern tree builtin_return_address_fndecl; + +extern struct obstack permanent_obstack; +extern struct obstack* saveable_obstack; + +extern int current_class_depth; + +extern tree static_ctors, static_dtors; + +extern int static_labelno; + +extern tree current_namespace; +extern tree global_namespace; + +extern void (*print_error_function) PROTO((char *)); +extern int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree)); + +/* Obstack used for remembering local class declarations (like + enums and static (const) members. */ +#include "stack.h" +struct obstack decl_obstack; +static struct stack_level *decl_stack; + +#ifndef CHAR_TYPE_SIZE +#define CHAR_TYPE_SIZE BITS_PER_UNIT +#endif + +#ifndef SHORT_TYPE_SIZE +#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2)) +#endif + +#ifndef INT_TYPE_SIZE +#define INT_TYPE_SIZE BITS_PER_WORD +#endif + +#ifndef LONG_TYPE_SIZE +#define LONG_TYPE_SIZE BITS_PER_WORD +#endif + +#ifndef LONG_LONG_TYPE_SIZE +#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2) +#endif + +#ifndef WCHAR_UNSIGNED +#define WCHAR_UNSIGNED 0 +#endif + +#ifndef FLOAT_TYPE_SIZE +#define FLOAT_TYPE_SIZE BITS_PER_WORD +#endif + +#ifndef DOUBLE_TYPE_SIZE +#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) +#endif + +#ifndef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) +#endif + +#ifndef BOOL_TYPE_SIZE +#ifdef SLOW_BYTE_ACCESS +#define BOOL_TYPE_SIZE ((SLOW_BYTE_ACCESS) ? (POINTER_SIZE) : (CHAR_TYPE_SIZE)) +#else +#define BOOL_TYPE_SIZE CHAR_TYPE_SIZE +#endif +#endif + +/* We let tm.h override the types used here, to handle trivial differences + such as the choice of unsigned int or long unsigned int for size_t. + When machines start needing nontrivial differences in the size type, + it would be best to do something here to figure out automatically + from other information what type to use. */ + +#ifndef SIZE_TYPE +#define SIZE_TYPE "long unsigned int" +#endif + +#ifndef PTRDIFF_TYPE +#define PTRDIFF_TYPE "long int" +#endif + +#ifndef WCHAR_TYPE +#define WCHAR_TYPE "int" +#endif + +static tree grokparms PROTO((tree, int)); +static tree lookup_nested_type PROTO((tree, tree)); +static const char *redeclaration_error_message PROTO((tree, tree)); + +static struct stack_level *push_decl_level PROTO((struct stack_level *, + struct obstack *)); +static void push_binding_level PROTO((struct binding_level *, int, + int)); +static void pop_binding_level PROTO((void)); +static void suspend_binding_level PROTO((void)); +static void resume_binding_level PROTO((struct binding_level *)); +static struct binding_level *make_binding_level PROTO((void)); +static void declare_namespace_level PROTO((void)); +static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN; +static void storedecls PROTO((tree)); +static void require_complete_types_for_parms PROTO((tree)); +static void push_overloaded_decl_1 PROTO((tree)); +static int ambi_op_p PROTO((tree)); +static int unary_op_p PROTO((tree)); +static tree store_bindings PROTO((tree, tree)); +static tree lookup_tag_reverse PROTO((tree, tree)); +static tree obscure_complex_init PROTO((tree, tree)); +static tree maybe_build_cleanup_1 PROTO((tree, tree)); +static tree lookup_name_real PROTO((tree, int, int, int)); +static void warn_extern_redeclared_static PROTO((tree, tree)); +static void grok_reference_init PROTO((tree, tree, tree)); +static tree grokfndecl PROTO((tree, tree, tree, tree, int, + enum overload_flags, tree, + tree, int, int, int, int, int, int, tree)); +static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int, tree)); +static tree lookup_tag PROTO((enum tree_code, tree, + struct binding_level *, int)); +static void set_identifier_type_value_with_scope + PROTO((tree, tree, struct binding_level *)); +static void record_builtin_type PROTO((enum rid, const char *, tree)); +static void record_unknown_type PROTO((tree, const char *)); +static int member_function_or_else PROTO((tree, tree, const char *)); +static void bad_specifiers PROTO((tree, const char *, int, int, int, int, + int)); +static void lang_print_error_function PROTO((char *)); +static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*)); +static void check_for_uninitialized_const_var PROTO((tree)); +static unsigned long typename_hash PROTO((hash_table_key)); +static boolean typename_compare PROTO((hash_table_key, hash_table_key)); +static void push_binding PROTO((tree, tree, struct binding_level*)); +static int add_binding PROTO((tree, tree)); +static void pop_binding PROTO((tree, tree)); +static tree local_variable_p PROTO((tree)); +static tree find_binding PROTO((tree, tree)); +static tree select_decl PROTO((tree, int)); +static tree unqualified_namespace_lookup PROTO((tree, int)); +static int lookup_flags PROTO((int, int)); +static tree qualify_lookup PROTO((tree, int)); +static tree record_builtin_java_type PROTO((const char *, int)); +static const char *tag_name PROTO((enum tag_types code)); +static void find_class_binding_level PROTO((void)); +static struct binding_level *innermost_nonclass_level PROTO((void)); +static void finish_dtor PROTO((void)); +static void finish_ctor PROTO((int)); +static tree poplevel_class PROTO((void)); +static void warn_about_implicit_typename_lookup PROTO((tree, tree)); +static int walk_namespaces_r PROTO((tree, walk_namespaces_fn, void *)); +static int walk_globals_r PROTO((tree, void *)); + +#if defined (DEBUG_CP_BINDING_LEVELS) +static void indent PROTO((void)); +#endif + +/* A node which has tree code ERROR_MARK, and whose type is itself. + All erroneous expressions are replaced with this node. All functions + that accept nodes as arguments should avoid generating error messages + if this node is one of the arguments, since it is undesirable to get + multiple error messages from one error in the input. */ + +tree error_mark_node; + +/* Erroneous argument lists can use this *IFF* they do not modify it. */ +tree error_mark_list; + +/* INTEGER_TYPE and REAL_TYPE nodes for the standard data types */ + +tree short_integer_type_node; +tree integer_type_node; +tree long_integer_type_node; +tree long_long_integer_type_node; + +tree short_unsigned_type_node; +tree unsigned_type_node; +tree long_unsigned_type_node; +tree long_long_unsigned_type_node; + +tree ptrdiff_type_node; + +tree unsigned_char_type_node; +tree signed_char_type_node; +tree char_type_node; +tree wchar_type_node; +tree signed_wchar_type_node; +tree unsigned_wchar_type_node; + +tree wchar_decl_node; + +tree float_type_node; +tree double_type_node; +tree long_double_type_node; + +tree complex_integer_type_node; +tree complex_float_type_node; +tree complex_double_type_node; +tree complex_long_double_type_node; + +tree intQI_type_node; +tree intHI_type_node; +tree intSI_type_node; +tree intDI_type_node; +#if HOST_BITS_PER_WIDE_INT >= 64 +tree intTI_type_node; +#endif + +tree unsigned_intQI_type_node; +tree unsigned_intHI_type_node; +tree unsigned_intSI_type_node; +tree unsigned_intDI_type_node; +#if HOST_BITS_PER_WIDE_INT >= 64 +tree unsigned_intTI_type_node; +#endif + +tree java_byte_type_node; +tree java_short_type_node; +tree java_int_type_node; +tree java_long_type_node; +tree java_float_type_node; +tree java_double_type_node; +tree java_char_type_node; +tree java_boolean_type_node; + +/* A VOID_TYPE node, and the same, packaged in a TREE_LIST. */ + +tree void_type_node, void_list_node; +tree void_zero_node; + +/* Nodes for types `void *' and `const void *'. */ + +tree ptr_type_node; +tree const_ptr_type_node; + +/* Nodes for types `char *' and `const char *'. */ + +tree string_type_node, const_string_type_node; + +/* Type `char[256]' or something like it. + Used when an array of char is needed and the size is irrelevant. */ + +tree char_array_type_node; + +/* Type `int[256]' or something like it. + Used when an array of int needed and the size is irrelevant. */ + +tree int_array_type_node; + +/* Type `wchar_t[256]' or something like it. + Used when a wide string literal is created. */ + +tree wchar_array_type_node; + +/* The bool data type, and constants */ +tree boolean_type_node, boolean_true_node, boolean_false_node; + +/* Type `int ()' -- used for implicit declaration of functions. */ + +tree default_function_type; + +/* Function types `double (double)' and `double (double, double)', etc. */ + +static tree double_ftype_double, double_ftype_double_double; +static tree int_ftype_int, long_ftype_long; +static tree float_ftype_float; +static tree ldouble_ftype_ldouble; + +/* Function type `int (const void *, const void *, size_t)' */ +static tree int_ftype_cptr_cptr_sizet; + +/* C++ extensions */ +tree vtable_entry_type; +tree delta_type_node; +#if 0 +/* Old rtti stuff. */ +tree __baselist_desc_type_node; +tree __i_desc_type_node, __m_desc_type_node; +tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type; +#endif +tree __t_desc_type_node; +#if 0 +tree __tp_desc_type_node; +#endif +tree __access_mode_type_node; +tree __bltn_desc_type_node, __user_desc_type_node, __class_desc_type_node; +tree __ptr_desc_type_node, __attr_desc_type_node, __func_desc_type_node; +tree __ptmf_desc_type_node, __ptmd_desc_type_node; +#if 0 +/* Not needed yet? May be needed one day? */ +tree __bltn_desc_array_type, __user_desc_array_type, __class_desc_array_type; +tree __ptr_desc_array_type, __attr_dec_array_type, __func_desc_array_type; +tree __ptmf_desc_array_type, __ptmd_desc_array_type; +#endif + +/* This is the identifier __vlist. */ +tree vlist_identifier; + +/* This is the type _Vlist = vtable_entry_type**. */ +tree vlist_type_node; + +/* A null pointer of type _Vlist. */ +tree vlist_zero_node; + +/* Indicates that there is a type value in some namespace, although + that is not necessarily in scope at the moment. */ + +static tree global_type_node; + +tree class_star_type_node; +tree class_type_node, record_type_node, union_type_node, enum_type_node; +tree unknown_type_node; +tree opaque_type_node, signature_type_node; +tree sigtable_entry_type; + +/* Array type `vtable_entry_type[]' */ +tree vtbl_type_node; +tree vtbl_ptr_type_node; + +/* namespace std */ +tree std_node; +int in_std = 0; + +/* Expect only namespace names now. */ +static int only_namespace_names; + +/* In a destructor, the point at which all derived class destroying + has been done, just before any base class destroying will be done. */ + +tree dtor_label; + +/* In a destructor, the last insn emitted after the start of the + function and the parms. */ + +static rtx last_dtor_insn; + +/* In a constructor, the last insn emitted after the start of the + function and the parms, the exception specification and any + function-try-block. The constructor initializers are emitted after + this insn. */ + +static rtx last_parm_cleanup_insn; + +/* In a constructor, the point at which we are ready to return + the pointer to the initialized object. */ + +tree ctor_label; + +/* A FUNCTION_DECL which can call `abort'. Not necessarily the + one that the user will declare, but sufficient to be called + by routines that want to abort the program. */ + +tree abort_fndecl; + +/* A FUNCTION_DECL for the default `::operator delete'. */ + +tree global_delete_fndecl; + +extern rtx cleanup_label, return_label; + +/* If original DECL_RESULT of current function was a register, + but due to being an addressable named return value, would up + on the stack, this variable holds the named return value's + original location. */ +static rtx original_result_rtx; + +/* Sequence of insns which represents base initialization. */ +tree base_init_expr; + +/* C++: Keep these around to reduce calls to `get_identifier'. + Identifiers for `this' in member functions and the auto-delete + parameter for destructors. */ +tree this_identifier, in_charge_identifier; +tree ctor_identifier, dtor_identifier; +/* Used in pointer to member functions, in vtables, and in sigtables. */ +tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier; +tree pfn_or_delta2_identifier, tag_identifier; +tree vt_off_identifier; + +struct named_label_list +{ + struct binding_level *binding_level; + tree names_in_scope; + tree label_decl; + char *filename_o_goto; + int lineno_o_goto; + struct named_label_list *next; +}; + +/* A list (chain of TREE_LIST nodes) of named label uses. + The TREE_PURPOSE field is the list of variables defined + in the label's scope defined at the point of use. + The TREE_VALUE field is the LABEL_DECL used. + The TREE_TYPE field holds `current_binding_level' at the + point of the label's use. + + BWAHAHAAHAHahhahahahaah. No, no, no, said the little chicken. + + Look at the pretty struct named_label_list. See the pretty struct + with the pretty named fields that describe what they do. See the + pretty lack of gratuitous casts. Notice the code got a lot cleaner. + + Used only for jumps to as-yet undefined labels, since + jumps to defined labels can have their validity checked + by stmt.c. */ + +static struct named_label_list *named_label_uses = NULL; + +/* A list of objects which have constructors or destructors + which reside in the global scope. The decl is stored in + the TREE_VALUE slot and the initializer is stored + in the TREE_PURPOSE slot. */ +tree static_aggregates; + +/* -- end of C++ */ + +/* Two expressions that are constants with value zero. + The first is of type `int', the second of type `void *'. */ + +tree integer_zero_node; +tree null_pointer_node; + +/* The value for __null (NULL), namely, a zero of an integer type with + the same number of bits as a pointer. */ +tree null_node; + +/* A node for the integer constants 1, 2, and 3. */ + +tree integer_one_node, integer_two_node, integer_three_node; + +/* While defining an enum type, this is 1 plus the last enumerator + constant value. */ + +static tree enum_next_value; + +/* Nonzero means that there was overflow computing enum_next_value. */ + +static int enum_overflow; + +/* Parsing a function declarator leaves a list of parameter names + or a chain or parameter decls here. */ + +tree last_function_parms; + +/* Parsing a function declarator leaves here a chain of structure + and enum types declared in the parmlist. */ + +static tree last_function_parm_tags; + +/* After parsing the declarator that starts a function definition, + `start_function' puts here the list of parameter names or chain of decls. + `store_parm_decls' finds it here. */ + +static tree current_function_parms; + +/* Similar, for last_function_parm_tags. */ +static tree current_function_parm_tags; + +/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function + that have names. Here so we can clear out their names' definitions + at the end of the function. */ + +static tree named_labels; + +/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */ + +static tree shadowed_labels; + +/* The FUNCTION_DECL for the function currently being compiled, + or 0 if between functions. */ +tree current_function_decl; + +/* Set to 0 at beginning of a function definition, set to 1 if + a return statement that specifies a return value is seen. */ + +int current_function_returns_value; + +/* Set to 0 at beginning of a function definition, set to 1 if + a return statement with no argument is seen. */ + +int current_function_returns_null; + +/* Set to 0 at beginning of a function definition, and whenever + a label (case or named) is defined. Set to value of expression + returned from function when that value can be transformed into + a named return value. */ + +tree current_function_return_value; + +/* Nonzero means give `double' the same size as `float'. */ + +extern int flag_short_double; + +/* Nonzero means don't recognize any builtin functions. */ + +extern int flag_no_builtin; + +/* Nonzero means don't recognize the non-ANSI builtin functions. + -ansi sets this. */ + +extern int flag_no_nonansi_builtin; + +/* Nonzero means enable obscure ANSI features and disable GNU extensions + that might cause ANSI-compliant code to be miscompiled. */ + +extern int flag_ansi; + +/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes) + objects. */ +extern int flag_huge_objects; + +/* Nonzero if we want to conserve space in the .o files. We do this + by putting uninitialized data and runtime initialized data into + .common instead of .data at the expense of not flagging multiple + definitions. */ +extern int flag_conserve_space; + +/* Pointers to the base and current top of the language name stack. */ + +extern tree *current_lang_base, *current_lang_stack; + +/* C and C++ flags are in decl2.c. */ + +/* Set to 0 at beginning of a constructor, set to 1 + if that function does an allocation before referencing its + instance variable. */ +static int current_function_assigns_this; +int current_function_just_assigned_this; + +/* Set to 0 at beginning of a function. Set non-zero when + store_parm_decls is called. Don't call store_parm_decls + if this flag is non-zero! */ +int current_function_parms_stored; + +/* Flag used when debugging spew.c */ + +extern int spew_debug; + +/* This is a copy of the class_shadowed list of the previous class binding + contour when at global scope. It's used to reset IDENTIFIER_CLASS_VALUEs + when entering another class scope (i.e. a cache miss). */ +extern tree previous_class_values; + +/* A expression of value 0 with the same precision as a sizetype + node, but signed. */ +tree signed_size_zero_node; + +/* The name of the anonymous namespace, throughout this translation + unit. */ +tree anonymous_namespace_name; + + +/* Allocate a level of searching. */ + +static +struct stack_level * +push_decl_level (stack, obstack) + struct stack_level *stack; + struct obstack *obstack; +{ + struct stack_level tem; + tem.prev = stack; + + return push_stack_level (obstack, (char *)&tem, sizeof (tem)); +} + +/* For each binding contour we allocate a binding_level structure + which records the names defined in that contour. + Contours include: + 0) the global one + 1) one for each function definition, + where internal declarations of the parameters appear. + 2) one for each compound statement, + to record its declarations. + + The current meaning of a name can be found by searching the levels + from the current one out to the global one. + + Off to the side, may be the class_binding_level. This exists only + to catch class-local declarations. It is otherwise nonexistent. + + Also there may be binding levels that catch cleanups that must be + run when exceptions occur. Thus, to see whether a name is bound in + the current scope, it is not enough to look in the + CURRENT_BINDING_LEVEL. You should use lookup_name_current_level + instead. */ + +/* Note that the information in the `names' component of the global contour + is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */ + +struct binding_level + { + /* A chain of _DECL nodes for all variables, constants, functions, + and typedef types. These are in the reverse of the order + supplied. There may be OVERLOADs on this list, too, but they + are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */ + tree names; + + /* A list of structure, union and enum definitions, for looking up + tag names. + It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name, + or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE, + or ENUMERAL_TYPE node. + + C++: the TREE_VALUE nodes can be simple types for + component_bindings. */ + tree tags; + + /* A list of USING_DECL nodes. */ + tree usings; + + /* A list of used namespaces. PURPOSE is the namespace, + VALUE the common ancestor with this binding_level's namespace. */ + tree using_directives; + + /* If this binding level is the binding level for a class, then + class_shadowed is a TREE_LIST. The TREE_PURPOSE of each node + is the name of an entity bound in the class; the TREE_VALUE is + the IDENTIFIER_CLASS_VALUE before we entered the class. Thus, + when leaving class scope, we can restore the + IDENTIFIER_CLASS_VALUE by walking this list. The TREE_TYPE is + the DECL bound by this name in the class. */ + tree class_shadowed; + + /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and + is used for all binding levels. */ + tree type_shadowed; + + /* For each level (except not the global one), + a chain of BLOCK nodes for all the levels + that were entered and exited one level down. */ + tree blocks; + + /* The BLOCK node for this level, if one has been preallocated. + If 0, the BLOCK is allocated (if needed) when the level is popped. */ + tree this_block; + + /* The binding level which this one is contained in (inherits from). */ + struct binding_level *level_chain; + + /* List of decls in `names' that have incomplete + structure or union types. */ + tree incomplete; + + /* List of VAR_DECLS saved from a previous for statement. + These would be dead in ANSI-conforming code, but might + be referenced in ARM-era code. These are stored in a + TREE_LIST; the TREE_VALUE is the actual declaration. */ + tree dead_vars_from_for; + + /* 1 for the level that holds the parameters of a function. + 2 for the level that holds a class declaration. + 3 for levels that hold parameter declarations. */ + unsigned parm_flag : 4; + + /* 1 means make a BLOCK for this level regardless of all else. + 2 for temporary binding contours created by the compiler. */ + unsigned keep : 3; + + /* Nonzero if this level "doesn't exist" for tags. */ + unsigned tag_transparent : 1; + + /* Nonzero if this level can safely have additional + cleanup-needing variables added to it. */ + unsigned more_cleanups_ok : 1; + unsigned have_cleanups : 1; + + /* Nonzero if this level is for storing the decls for template + parameters and generic decls; these decls will be discarded and + replaced with a TEMPLATE_DECL. */ + unsigned pseudo_global : 1; + + /* This is set for a namespace binding level. */ + unsigned namespace_p : 1; + + /* True if this level is that of a for-statement where we need to + worry about ambiguous (ARM or ANSI) scope rules. */ + unsigned is_for_scope : 1; + + /* Two bits left for this word. */ + +#if defined(DEBUG_CP_BINDING_LEVELS) + /* Binding depth at which this level began. */ + unsigned binding_depth; +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ + }; + +#define NULL_BINDING_LEVEL ((struct binding_level *) NULL) + +/* The binding level currently in effect. */ + +static struct binding_level *current_binding_level; + +/* The binding level of the current class, if any. */ + +static struct binding_level *class_binding_level; + +/* A chain of binding_level structures awaiting reuse. */ + +static struct binding_level *free_binding_level; + +/* The outermost binding level, for names of file scope. + This is created when the compiler is started and exists + through the entire run. */ + +static struct binding_level *global_binding_level; + +/* Binding level structures are initialized by copying this one. */ + +static struct binding_level clear_binding_level; + +/* Nonzero means unconditionally make a BLOCK for the next level pushed. */ + +static int keep_next_level_flag; + +#if defined(DEBUG_CP_BINDING_LEVELS) +static int binding_depth = 0; +static int is_class_level = 0; + +static void +indent () +{ + register unsigned i; + + for (i = 0; i < binding_depth*2; i++) + putc (' ', stderr); +} +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ + +static tree pushdecl_with_scope PROTO((tree, struct binding_level *)); + +static void +push_binding_level (newlevel, tag_transparent, keep) + struct binding_level *newlevel; + int tag_transparent, keep; +{ + /* Add this level to the front of the chain (stack) of levels that + are active. */ + *newlevel = clear_binding_level; + newlevel->level_chain = current_binding_level; + current_binding_level = newlevel; + newlevel->tag_transparent = tag_transparent; + newlevel->more_cleanups_ok = 1; + newlevel->keep = keep; +#if defined(DEBUG_CP_BINDING_LEVELS) + newlevel->binding_depth = binding_depth; + indent (); + fprintf (stderr, "push %s level 0x%08x line %d\n", + (is_class_level) ? "class" : "block", newlevel, lineno); + is_class_level = 0; + binding_depth++; +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ +} + +/* Find the innermost enclosing class scope, and reset + CLASS_BINDING_LEVEL appropriately. */ + +static void +find_class_binding_level () +{ + struct binding_level *level = current_binding_level; + + while (level && level->parm_flag != 2) + level = level->level_chain; + if (level && level->parm_flag == 2) + class_binding_level = level; + else + class_binding_level = 0; +} + +static void +pop_binding_level () +{ + if (global_binding_level) + { + /* Cannot pop a level, if there are none left to pop. */ + if (current_binding_level == global_binding_level) + my_friendly_abort (123); + } + /* Pop the current level, and free the structure for reuse. */ +#if defined(DEBUG_CP_BINDING_LEVELS) + binding_depth--; + indent (); + fprintf (stderr, "pop %s level 0x%08x line %d\n", + (is_class_level) ? "class" : "block", + current_binding_level, lineno); + if (is_class_level != (current_binding_level == class_binding_level)) + { + indent (); + fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n"); + } + is_class_level = 0; +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ + { + register struct binding_level *level = current_binding_level; + current_binding_level = current_binding_level->level_chain; + level->level_chain = free_binding_level; +#if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */ + if (level->binding_depth != binding_depth) + abort (); +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ + free_binding_level = level; + find_class_binding_level (); + } +} + +static void +suspend_binding_level () +{ + if (class_binding_level) + current_binding_level = class_binding_level; + + if (global_binding_level) + { + /* Cannot suspend a level, if there are none left to suspend. */ + if (current_binding_level == global_binding_level) + my_friendly_abort (123); + } + /* Suspend the current level. */ +#if defined(DEBUG_CP_BINDING_LEVELS) + binding_depth--; + indent (); + fprintf (stderr, "suspend %s level 0x%08x line %d\n", + (is_class_level) ? "class" : "block", + current_binding_level, lineno); + if (is_class_level != (current_binding_level == class_binding_level)) + { + indent (); + fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n"); + } + is_class_level = 0; +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ + current_binding_level = current_binding_level->level_chain; + find_class_binding_level (); +} + +static void +resume_binding_level (b) + struct binding_level *b; +{ + /* Resuming binding levels is meant only for namespaces, + and those cannot nest into classes. */ + my_friendly_assert(!class_binding_level, 386); + /* Also, resuming a non-directly nested namespace is a no-no. */ + my_friendly_assert(b->level_chain == current_binding_level, 386); + current_binding_level = b; +#if defined(DEBUG_CP_BINDING_LEVELS) + b->binding_depth = binding_depth; + indent (); + fprintf (stderr, "resume %s level 0x%08x line %d\n", + (is_class_level) ? "class" : "block", b, lineno); + is_class_level = 0; + binding_depth++; +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ +} + +/* Create a new `struct binding_level'. */ + +static +struct binding_level * +make_binding_level () +{ + /* NOSTRICT */ + return (struct binding_level *) xmalloc (sizeof (struct binding_level)); +} + +/* Nonzero if we are currently in the global binding level. */ + +int +global_bindings_p () +{ + return current_binding_level == global_binding_level; +} + +/* Return the innermost binding level that is not for a class scope. */ + +static struct binding_level * +innermost_nonclass_level () +{ + struct binding_level *b; + + b = current_binding_level; + while (b->parm_flag == 2) + b = b->level_chain; + + return b; +} + +/* Nonzero if we are currently in a toplevel binding level. This + means either the global binding level or a namespace in a toplevel + binding level. Since there are no non-toplevel namespace levels, + this really means any namespace or pseudo-global level. We also + include a class whose context is toplevel. */ + +int +toplevel_bindings_p () +{ + struct binding_level *b = innermost_nonclass_level (); + + return b->namespace_p || b->pseudo_global; +} + +/* Nonzero if this is a namespace scope, or if we are defining a class + which is itself at namespace scope, or whose enclosing class is + such a class, etc. */ + +int +namespace_bindings_p () +{ + struct binding_level *b = innermost_nonclass_level (); + + return b->namespace_p; +} + +void +keep_next_level () +{ + keep_next_level_flag = 1; +} + +/* Nonzero if the current level needs to have a BLOCK made. */ + +int +kept_level_p () +{ + return (current_binding_level->blocks != NULL_TREE + || current_binding_level->keep + || current_binding_level->names != NULL_TREE + || (current_binding_level->tags != NULL_TREE + && !current_binding_level->tag_transparent)); +} + +/* Identify this binding level as a level of parameters. */ + +void +declare_parm_level () +{ + current_binding_level->parm_flag = 1; +} + +void +declare_pseudo_global_level () +{ + current_binding_level->pseudo_global = 1; +} + +static void +declare_namespace_level () +{ + current_binding_level->namespace_p = 1; +} + +int +pseudo_global_level_p () +{ + struct binding_level *b = innermost_nonclass_level (); + + return b->pseudo_global; +} + +void +set_class_shadows (shadows) + tree shadows; +{ + class_binding_level->class_shadowed = shadows; +} + +/* Enter a new binding level. + If TAG_TRANSPARENT is nonzero, do so only for the name space of variables, + not for that of tags. */ + +void +pushlevel (tag_transparent) + int tag_transparent; +{ + register struct binding_level *newlevel = NULL_BINDING_LEVEL; + + /* If this is the top level of a function, + just make sure that NAMED_LABELS is 0. + They should have been set to 0 at the end of the previous function. */ + + if (current_binding_level == global_binding_level) + my_friendly_assert (named_labels == NULL_TREE, 134); + + /* Reuse or create a struct for this binding level. */ + +#if defined(DEBUG_CP_BINDING_LEVELS) + if (0) +#else /* !defined(DEBUG_CP_BINDING_LEVELS) */ + if (free_binding_level) +#endif /* !defined(DEBUG_CP_BINDING_LEVELS) */ + { + newlevel = free_binding_level; + free_binding_level = free_binding_level->level_chain; + } + else + { + newlevel = make_binding_level (); + } + + push_binding_level (newlevel, tag_transparent, keep_next_level_flag); + GNU_xref_start_scope ((HOST_WIDE_INT) newlevel); + keep_next_level_flag = 0; +} + +void +note_level_for_for () +{ + current_binding_level->is_for_scope = 1; +} + +void +pushlevel_temporary (tag_transparent) + int tag_transparent; +{ + pushlevel (tag_transparent); + current_binding_level->keep = 2; + clear_last_expr (); + + /* Note we don't call push_momentary() here. Otherwise, it would cause + cleanups to be allocated on the momentary obstack, and they will be + overwritten by the next statement. */ + + expand_start_bindings (0); +} + +/* For a binding between a name and an entity at a block scope, + this is the `struct binding_level' for the block. */ +#define BINDING_LEVEL(NODE) \ + (((struct tree_binding*)NODE)->scope.level) + +/* These are currently unused, but permanent, CPLUS_BINDING nodes. + They are kept here because they are allocated from the permanent + obstack and cannot be easily freed. */ +static tree free_binding_nodes; + +/* Make DECL the innermost binding for ID. The LEVEL is the binding + level at which this declaration is being bound. */ + +static void +push_binding (id, decl, level) + tree id; + tree decl; + struct binding_level* level; +{ + tree binding; + + if (!free_binding_nodes) + { + /* There are no free nodes, so we must build one here. */ + push_obstacks_nochange (); + end_temporary_allocation (); + binding = make_node (CPLUS_BINDING); + pop_obstacks (); + } + else + { + /* There are nodes on the free list. Grab the first one. */ + binding = free_binding_nodes; + + /* And update the free list. */ + free_binding_nodes = TREE_CHAIN (free_binding_nodes); + } + + /* Now, fill in the binding information. */ + BINDING_VALUE (binding) = decl; + BINDING_TYPE (binding) = NULL_TREE; + BINDING_LEVEL (binding) = level; + INHERITED_VALUE_BINDING_P (binding) = 0; + LOCAL_BINDING_P (binding) = (level != class_binding_level); + + /* And put it on the front of the list of bindings for ID. */ + TREE_CHAIN (binding) = IDENTIFIER_BINDING (id); + IDENTIFIER_BINDING (id) = binding; +} + +/* ID is already bound in the current scope. But, DECL is an + additional binding for ID in the same scope. This is the `struct + stat' hack whereby a non-typedef class-name or enum-name can be + bound at the same level as some other kind of entity. It's the + responsibility of the caller to check that inserting this name is + legal here. Returns nonzero if the new binding was successful. */ +static int +add_binding (id, decl) + tree id; + tree decl; +{ + tree binding = IDENTIFIER_BINDING (id); + int ok = 1; + + if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)) + /* The new name is the type name. */ + BINDING_TYPE (binding) = decl; + else if (!BINDING_VALUE (binding)) + /* This situation arises when push_class_level_binding moves an + inherited type-binding out of the way to make room for a new + value binding. */ + BINDING_VALUE (binding) = decl; + else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL + && DECL_ARTIFICIAL (BINDING_VALUE (binding))) + { + /* The old binding was a type name. It was placed in + BINDING_VALUE because it was thought, at the point it was + declared, to be the only entity with such a name. Move the + type name into the type slot; it is now hidden by the new + binding. */ + BINDING_TYPE (binding) = BINDING_VALUE (binding); + BINDING_VALUE (binding) = decl; + INHERITED_VALUE_BINDING_P (binding) = 0; + } + else + { + cp_error ("declaration of `%#D'", decl); + cp_error_at ("conflicts with previous declaration `%#D'", + BINDING_VALUE (binding)); + ok = 0; + } + + return ok; +} + +/* Bind DECL to ID in the current_binding_level. + If PUSH_USING is set in FLAGS, we know that DECL doesn't really belong + to this binding level, that it got here through a using-declaration. */ + +void +push_local_binding (id, decl, flags) + tree id; + tree decl; + int flags; +{ + struct binding_level *b; + + /* Skip over any local classes. This makes sense if we call + push_local_binding with a friend decl of a local class. */ + b = current_binding_level; + while (b->parm_flag == 2) + b = b->level_chain; + + if (lookup_name_current_level (id)) + { + /* Supplement the existing binding. */ + if (!add_binding (id, decl)) + /* It didn't work. Something else must be bound at this + level. Do not add DECL to the list of things to pop + later. */ + return; + } + else + /* Create a new binding. */ + push_binding (id, decl, b); + + if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING)) + /* We must put the OVERLOAD into a TREE_LIST since the + TREE_CHAIN of an OVERLOAD is already used. Similarly for + decls that got here through a using-declaration. */ + decl = build_tree_list (NULL_TREE, decl); + + /* And put DECL on the list of things declared by the current + binding level. */ + TREE_CHAIN (decl) = b->names; + b->names = decl; +} + +/* Bind DECL to ID in the class_binding_level. Returns nonzero if the + binding was successful. */ + +int +push_class_binding (id, decl) + tree id; + tree decl; +{ + int result = 1; + tree binding = IDENTIFIER_BINDING (id); + tree context; + + /* Note that we declared this value so that we can issue an error if + this an illegal redeclaration of a name already used for some + other purpose. */ + note_name_declared_in_class (id, decl); + + if (binding && BINDING_LEVEL (binding) == class_binding_level) + /* Supplement the existing binding. */ + result = add_binding (id, decl); + else + /* Create a new binding. */ + push_binding (id, decl, class_binding_level); + + /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the + class-level declaration. Note that we do not use DECL here + because of the possibility of the `struct stat' hack; if DECL is + a class-name or enum-name we might prefer a field-name, or some + such. */ + IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id)); + + /* If this is a binding from a base class, mark it as such. */ + binding = IDENTIFIER_BINDING (id); + if (BINDING_VALUE (binding) == decl && TREE_CODE (decl) != TREE_LIST) + { + /* Any implicit typename must be from a base-class. The + context for an implicit typename declaration is always + the derived class in which the lookup was done, so the checks + based on the context of DECL below will not trigger. */ + if (TREE_CODE (decl) == TYPE_DECL + && IMPLICIT_TYPENAME_P (TREE_TYPE (decl))) + INHERITED_VALUE_BINDING_P (binding) = 1; + else + { + if (TREE_CODE (decl) == OVERLOAD) + context = DECL_REAL_CONTEXT (OVL_CURRENT (decl)); + else + { + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', + 0); + context = DECL_REAL_CONTEXT (decl); + } + + if (is_properly_derived_from (current_class_type, context)) + INHERITED_VALUE_BINDING_P (binding) = 1; + else + INHERITED_VALUE_BINDING_P (binding) = 0; + } + } + else if (BINDING_VALUE (binding) == decl) + /* We only encounter a TREE_LIST when push_class_decls detects an + ambiguity. Such an ambiguity can be overridden by a definition + in this class. */ + INHERITED_VALUE_BINDING_P (binding) = 1; + + return result; +} + +/* Remove the binding for DECL which should be the innermost binding + for ID. */ + +static void +pop_binding (id, decl) + tree id; + tree decl; +{ + tree binding; + + if (id == NULL_TREE) + /* It's easiest to write the loops that call this function without + checking whether or not the entities involved have names. We + get here for such an entity. */ + return; + + /* Get the innermost binding for ID. */ + binding = IDENTIFIER_BINDING (id); + + /* The name should be bound. */ + my_friendly_assert (binding != NULL_TREE, 0); + + /* The DECL will be either the ordinary binding or the type + binding for this identifier. Remove that binding. */ + if (BINDING_VALUE (binding) == decl) + BINDING_VALUE (binding) = NULL_TREE; + else if (BINDING_TYPE (binding) == decl) + BINDING_TYPE (binding) = NULL_TREE; + else + my_friendly_abort (0); + + if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding)) + { + /* We're completely done with the innermost binding for this + identifier. Unhook it from the list of bindings. */ + IDENTIFIER_BINDING (id) = TREE_CHAIN (binding); + + /* And place it on the free list. */ + TREE_CHAIN (binding) = free_binding_nodes; + free_binding_nodes = binding; + } +} + +/* Exit a binding level. + Pop the level off, and restore the state of the identifier-decl mappings + that were in effect when this level was entered. + + If KEEP == 1, this level had explicit declarations, so + and create a "block" (a BLOCK node) for the level + to record its declarations and subblocks for symbol table output. + + If FUNCTIONBODY is nonzero, this level is the body of a function, + so create a block as if KEEP were set and also clear out all + label names. + + If REVERSE is nonzero, reverse the order of decls before putting + them into the BLOCK. */ + +tree +poplevel (keep, reverse, functionbody) + int keep; + int reverse; + int functionbody; +{ + register tree link; + /* The chain of decls was accumulated in reverse order. + Put it into forward order, just for cleanliness. */ + tree decls; + int tmp = functionbody; + int real_functionbody = current_binding_level->keep == 2 + ? ((functionbody = 0), tmp) : functionbody; + tree tags = functionbody >= 0 ? current_binding_level->tags : 0; + tree subblocks = functionbody >= 0 ? current_binding_level->blocks : 0; + tree block = NULL_TREE; + tree decl; + int block_previously_created; + int leaving_for_scope; + + if (current_binding_level->parm_flag == 2) + return poplevel_class (); + + my_friendly_assert (!current_binding_level->class_shadowed, + 19990414); + + /* We used to use KEEP == 2 to indicate that the new block should go + at the beginning of the list of blocks at this binding level, + rather than the end. This hack is no longer used. */ + my_friendly_assert (keep == 0 || keep == 1, 0); + + GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level, + (HOST_WIDE_INT) current_binding_level->level_chain, + current_binding_level->parm_flag, + current_binding_level->keep); + + if (current_binding_level->keep == 1) + keep = 1; + + /* Get the decls in the order they were written. + Usually current_binding_level->names is in reverse order. + But parameter decls were previously put in forward order. */ + + if (reverse) + current_binding_level->names + = decls = nreverse (current_binding_level->names); + else + decls = current_binding_level->names; + + /* Output any nested inline functions within this block + if they weren't already output. */ + + for (decl = decls; decl; decl = TREE_CHAIN (decl)) + if (TREE_CODE (decl) == FUNCTION_DECL + && ! TREE_ASM_WRITTEN (decl) + && DECL_INITIAL (decl) != NULL_TREE + && TREE_ADDRESSABLE (decl) + && decl_function_context (decl) == current_function_decl) + { + /* If this decl was copied from a file-scope decl + on account of a block-scope extern decl, + propagate TREE_ADDRESSABLE to the file-scope decl. */ + if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE) + TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1; + else + { + push_function_context (); + output_inline_function (decl); + pop_function_context (); + } + } + + /* If there were any declarations or structure tags in that level, + or if this level is a function body, + create a BLOCK to record them for the life of this function. */ + + block = NULL_TREE; + block_previously_created = (current_binding_level->this_block != NULL_TREE); + if (block_previously_created) + block = current_binding_level->this_block; + else if (keep == 1 || functionbody) + block = make_node (BLOCK); + if (block != NULL_TREE) + { + if (block_previously_created) + { + if (decls || tags || subblocks) + { + if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block)) + warning ("internal compiler error: debugging info corrupted"); + + BLOCK_VARS (block) = decls; + BLOCK_TYPE_TAGS (block) = tags; + + /* We can have previous subblocks and new subblocks when + doing fixup_gotos with complex cleanups. We chain the new + subblocks onto the end of any pre-existing subblocks. */ + BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block), + subblocks); + } + /* If we created the block earlier on, and we are just + diddling it now, then it already should have a proper + BLOCK_END_NOTE value associated with it. */ + } + else + { + BLOCK_VARS (block) = decls; + BLOCK_TYPE_TAGS (block) = tags; + BLOCK_SUBBLOCKS (block) = subblocks; + /* Otherwise, for a new block, install a new BLOCK_END_NOTE + value. */ + remember_end_note (block); + } + } + + /* In each subblock, record that this is its superior. */ + + if (keep >= 0) + for (link = subblocks; link; link = TREE_CHAIN (link)) + BLOCK_SUPERCONTEXT (link) = block; + + /* We still support the old for-scope rules, whereby the variables + in a for-init statement were in scope after the for-statement + ended. We only use the new rules in flag_new_for_scope is + nonzero. */ + leaving_for_scope + = current_binding_level->is_for_scope && flag_new_for_scope == 1; + + /* Remove declarations for all the DECLs in this level. */ + for (link = decls; link; link = TREE_CHAIN (link)) + { + if (leaving_for_scope && TREE_CODE (link) == VAR_DECL) + { + tree outer_binding + = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link))); + tree ns_binding; + + if (!outer_binding) + ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link)); + else + ns_binding = NULL_TREE; + + if (outer_binding + && (BINDING_LEVEL (outer_binding) + == current_binding_level->level_chain)) + /* We have something like: + + int i; + for (int i; ;); + + and we are leaving the `for' scope. There's no reason to + keep the binding of the inner `i' in this case. */ + pop_binding (DECL_NAME (link), link); + else if ((outer_binding + && (TREE_CODE (BINDING_VALUE (outer_binding)) + == TYPE_DECL)) + || (ns_binding + && TREE_CODE (ns_binding) == TYPE_DECL)) + /* Here, we have something like: + + typedef int I; + + void f () { + for (int I; ;); + } + + We must pop the for-scope binding so we know what's a + type and what isn't. */ + pop_binding (DECL_NAME (link), link); + else + { + /* Mark this VAR_DECL as dead so that we can tell we left it + there only for backward compatibility. */ + DECL_DEAD_FOR_LOCAL (link) = 1; + + /* Keep track of what should of have happenned when we + popped the binding. */ + if (outer_binding && BINDING_VALUE (outer_binding)) + DECL_SHADOWED_FOR_VAR (link) + = BINDING_VALUE (outer_binding); + + /* Add it to the list of dead variables in the next + outermost binding to that we can remove these when we + leave that binding. */ + current_binding_level->level_chain->dead_vars_from_for + = tree_cons (NULL_TREE, link, + current_binding_level->level_chain-> + dead_vars_from_for); + + /* Although we don't pop the CPLUS_BINDING, we do clear + its BINDING_LEVEL since the level is going away now. */ + BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link))) + = 0; + } + } + else + { + /* Remove the binding. */ + decl = link; + if (TREE_CODE (decl) == TREE_LIST) + decl = TREE_VALUE (decl); + if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') + pop_binding (DECL_NAME (decl), decl); + else if (TREE_CODE (decl) == OVERLOAD) + pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl); + else + my_friendly_abort (0); + } + } + + /* Remove declarations for any `for' variables from inner scopes + that we kept around. */ + for (link = current_binding_level->dead_vars_from_for; + link; link = TREE_CHAIN (link)) + pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link)); + + /* Restore the IDENTIFIER_TYPE_VALUEs. */ + for (link = current_binding_level->type_shadowed; + link; link = TREE_CHAIN (link)) + SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link)); + + /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs + list if a `using' declaration put them there. The debugging + back-ends won't understand OVERLOAD, so we remove them here. + Because the BLOCK_VARS are (temporarily) shared with + CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have + popped all the bindings. */ + if (block) + { + tree* d; + + for (d = &BLOCK_VARS (block); *d; ) + { + if (TREE_CODE (*d) == TREE_LIST) + *d = TREE_CHAIN (*d); + else + d = &TREE_CHAIN (*d); + } + } + + /* If the level being exited is the top level of a function, + check over all the labels. */ + + if (functionbody) + { + /* If this is the top level block of a function, + the vars are the function's parameters. + Don't leave them in the BLOCK because they are + found in the FUNCTION_DECL instead. */ + + BLOCK_VARS (block) = 0; + + /* Clear out the definitions of all label names, + since their scopes end here. */ + + for (link = named_labels; link; link = TREE_CHAIN (link)) + { + register tree label = TREE_VALUE (link); + + if (DECL_INITIAL (label) == NULL_TREE) + { + cp_error_at ("label `%D' used but not defined", label); + /* Avoid crashing later. */ + define_label (input_filename, 1, DECL_NAME (label)); + } + else if (warn_unused && !TREE_USED (label)) + cp_warning_at ("label `%D' defined but not used", label); + SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), NULL_TREE); + + /* Put the labels into the "variables" of the + top-level block, so debugger can see them. */ + TREE_CHAIN (label) = BLOCK_VARS (block); + BLOCK_VARS (block) = label; + } + + named_labels = NULL_TREE; + } + + /* Any uses of undefined labels now operate under constraints + of next binding contour. */ + { + struct binding_level *level_chain; + level_chain = current_binding_level->level_chain; + if (level_chain) + { + struct named_label_list *labels; + for (labels = named_label_uses; labels; labels = labels->next) + if (labels->binding_level == current_binding_level) + { + labels->binding_level = level_chain; + labels->names_in_scope = level_chain->names; + } + } + } + + tmp = current_binding_level->keep; + + pop_binding_level (); + if (functionbody) + DECL_INITIAL (current_function_decl) = block; + else if (block) + { + if (!block_previously_created) + current_binding_level->blocks + = chainon (current_binding_level->blocks, block); + } + /* If we did not make a block for the level just exited, + any blocks made for inner levels + (since they cannot be recorded as subblocks in that level) + must be carried forward so they will later become subblocks + of something else. */ + else if (subblocks) + current_binding_level->blocks + = chainon (current_binding_level->blocks, subblocks); + + /* Take care of compiler's internal binding structures. */ + if (tmp == 2) + { + expand_end_bindings (getdecls (), keep, 1); + /* Each and every BLOCK node created here in `poplevel' is important + (e.g. for proper debugging information) so if we created one + earlier, mark it as "used". */ + if (block) + TREE_USED (block) = 1; + block = poplevel (keep, reverse, real_functionbody); + } + + /* Each and every BLOCK node created here in `poplevel' is important + (e.g. for proper debugging information) so if we created one + earlier, mark it as "used". */ + if (block) + TREE_USED (block) = 1; + return block; +} + +/* Delete the node BLOCK from the current binding level. + This is used for the block inside a stmt expr ({...}) + so that the block can be reinserted where appropriate. */ + +void +delete_block (block) + tree block; +{ + tree t; + if (current_binding_level->blocks == block) + current_binding_level->blocks = TREE_CHAIN (block); + for (t = current_binding_level->blocks; t;) + { + if (TREE_CHAIN (t) == block) + TREE_CHAIN (t) = TREE_CHAIN (block); + else + t = TREE_CHAIN (t); + } + TREE_CHAIN (block) = NULL_TREE; + /* Clear TREE_USED which is always set by poplevel. + The flag is set again if insert_block is called. */ + TREE_USED (block) = 0; +} + +/* Insert BLOCK at the end of the list of subblocks of the + current binding level. This is used when a BIND_EXPR is expanded, + to handle the BLOCK node inside the BIND_EXPR. */ + +void +insert_block (block) + tree block; +{ + TREE_USED (block) = 1; + current_binding_level->blocks + = chainon (current_binding_level->blocks, block); +} + +/* Set the BLOCK node for the innermost scope + (the one we are currently in). */ + +void +set_block (block) + register tree block; +{ + current_binding_level->this_block = block; +} + +/* Do a pushlevel for class declarations. */ + +void +pushlevel_class () +{ + register struct binding_level *newlevel; + + /* Reuse or create a struct for this binding level. */ +#if defined(DEBUG_CP_BINDING_LEVELS) + if (0) +#else /* !defined(DEBUG_CP_BINDING_LEVELS) */ + if (free_binding_level) +#endif /* !defined(DEBUG_CP_BINDING_LEVELS) */ + { + newlevel = free_binding_level; + free_binding_level = free_binding_level->level_chain; + } + else + newlevel = make_binding_level (); + +#if defined(DEBUG_CP_BINDING_LEVELS) + is_class_level = 1; +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ + + push_binding_level (newlevel, 0, 0); + + decl_stack = push_decl_level (decl_stack, &decl_obstack); + class_binding_level = current_binding_level; + class_binding_level->parm_flag = 2; +} + +/* ...and a poplevel for class declarations. */ + +static tree +poplevel_class () +{ + register struct binding_level *level = class_binding_level; + tree shadowed; + + my_friendly_assert (level != 0, 354); + + decl_stack = pop_stack_level (decl_stack); + /* If we're leaving a toplevel class, don't bother to do the setting + of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot + shouldn't even be used when current_class_type isn't set, and second, + if we don't touch it here, we're able to use the cache effect if the + next time we're entering a class scope, it is the same class. */ + if (current_class_depth != 1) + { + struct binding_level* b; + + /* Clear out our IDENTIFIER_CLASS_VALUEs. */ + for (shadowed = level->class_shadowed; + shadowed; + shadowed = TREE_CHAIN (shadowed)) + IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE; + + /* Find the next enclosing class, and recreate + IDENTIFIER_CLASS_VALUEs appropriate for that class. */ + b = level->level_chain; + while (b && b->parm_flag != 2) + b = b->level_chain; + + if (b) + for (shadowed = b->class_shadowed; + shadowed; + shadowed = TREE_CHAIN (shadowed)) + { + tree t; + + t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed)); + while (t && BINDING_LEVEL (t) != b) + t = TREE_CHAIN (t); + + if (t) + IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) + = BINDING_VALUE (t); + } + } + else + /* Remember to save what IDENTIFIER's were bound in this scope so we + can recover from cache misses. */ + { + previous_class_type = current_class_type; + previous_class_values = class_binding_level->class_shadowed; + } + for (shadowed = level->type_shadowed; + shadowed; + shadowed = TREE_CHAIN (shadowed)) + SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed)); + + /* Remove the bindings for all of the class-level declarations. */ + for (shadowed = level->class_shadowed; + shadowed; + shadowed = TREE_CHAIN (shadowed)) + pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed)); + + GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level, + (HOST_WIDE_INT) class_binding_level->level_chain, + class_binding_level->parm_flag, + class_binding_level->keep); + + /* Now, pop out of the binding level which we created up in the + `pushlevel_class' routine. */ +#if defined(DEBUG_CP_BINDING_LEVELS) + is_class_level = 1; +#endif /* defined(DEBUG_CP_BINDING_LEVELS) */ + + pop_binding_level (); + + return NULL_TREE; +} + +/* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE + for any names in enclosing classes. */ + +void +clear_identifier_class_values () +{ + tree t; + + if (!class_binding_level) + return; + + for (t = class_binding_level->class_shadowed; + t; + t = TREE_CHAIN (t)) + IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE; +} + +/* Returns non-zero if T is a virtual function table. */ + +int +vtable_decl_p (t, data) + tree t; + void *data ATTRIBUTE_UNUSED; +{ + return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t)); +} + +/* Returns non-zero if T is a TYPE_DECL for a type with virtual + functions. */ + +int +vtype_decl_p (t, data) + tree t; + void *data ATTRIBUTE_UNUSED; +{ + return (TREE_CODE (t) == TYPE_DECL + && TREE_TYPE (t) != error_mark_node + && TYPE_LANG_SPECIFIC (TREE_TYPE (t)) + && CLASSTYPE_VSIZE (TREE_TYPE (t))); +} + +/* Returns non-zero if T is a signature table. */ + +int +sigtable_decl_p (t, data) + tree t; + void *data ATTRIBUTE_UNUSED; +{ + return (TREE_CODE (t) == VAR_DECL + && TREE_TYPE (t) != error_mark_node + && IS_SIGNATURE (TREE_TYPE (t))); +} + +/* Walk all the namespaces contained NAMESPACE, including NAMESPACE + itself, calling F for each. The DATA is passed to F as well. */ + +static int +walk_namespaces_r (namespace, f, data) + tree namespace; + walk_namespaces_fn f; + void *data; +{ + tree current; + int result = 0; + + result |= (*f) (namespace, data); + + for (current = NAMESPACE_LEVEL (namespace)->names; + current; + current = TREE_CHAIN (current)) + { + if (TREE_CODE (current) != NAMESPACE_DECL + || DECL_NAMESPACE_ALIAS (current)) + continue; + if (!DECL_LANG_SPECIFIC (current)) + { + /* Hmm. std. */ + my_friendly_assert (current == std_node, 393); + continue; + } + + /* We found a namespace. */ + result |= walk_namespaces_r (current, f, data); + } + + return result; +} + +/* Walk all the namespaces, calling F for each. The DATA is passed to + F as well. */ + +int +walk_namespaces (f, data) + walk_namespaces_fn f; + void *data; +{ + return walk_namespaces_r (global_namespace, f, data); +} + +struct walk_globals_data { + walk_globals_pred p; + walk_globals_fn f; + void *data; +}; + +/* Walk the global declarations in NAMESPACE. Whenever one is found + for which P returns non-zero, call F with its address. If any call + to F returns a non-zero value, return a non-zero value. */ + +static int +walk_globals_r (namespace, data) + tree namespace; + void *data; +{ + struct walk_globals_data* wgd = (struct walk_globals_data *) data; + walk_globals_pred p = wgd->p; + walk_globals_fn f = wgd->f; + void *d = wgd->data; + tree *t; + int result = 0; + + t = &NAMESPACE_LEVEL (namespace)->names; + + while (*t) + { + tree glbl = *t; + + if ((*p) (glbl, d)) + result |= (*f) (t, d); + + /* If F changed *T, then *T still points at the next item to + examine. */ + if (*t == glbl) + t = &TREE_CHAIN (*t); + } + + return result; +} + +/* Walk the global declarations. Whenever one is found for which P + returns non-zero, call F with its address. If any call to F + returns a non-zero value, return a non-zero value. */ + +int +walk_globals (p, f, data) + walk_globals_pred p; + walk_globals_fn f; + void *data; +{ + struct walk_globals_data wgd; + wgd.p = p; + wgd.f = f; + wgd.data = data; + + return walk_namespaces (walk_globals_r, &wgd); +} + +/* Call wrapup_globals_declarations for the globals in NAMESPACE. If + DATA is non-NULL, this is the last time we will call + wrapup_global_declarations for this NAMESPACE. */ + +int +wrapup_globals_for_namespace (namespace, data) + tree namespace; + void *data; +{ + tree globals = NAMESPACE_LEVEL (namespace)->names; + int len = list_length (globals); + tree *vec = (tree *) alloca (sizeof (tree) * len); + int i; + int result; + tree decl; + int last_time = (data != 0); + + if (last_time && namespace == global_namespace) + /* Let compile_file handle the global namespace. */ + return 0; + + /* Process the decls in reverse order--earliest first. + Put them into VEC from back to front, then take out from front. */ + + for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) + vec[len - i - 1] = decl; + + if (last_time) + { + check_global_declarations (vec, len); + return 0; + } + + /* Temporarily mark vtables as external. That prevents + wrapup_global_declarations from writing them out; we must process + them ourselves in finish_vtable_vardecl. */ + for (i = 0; i < len; ++i) + if (vtable_decl_p (vec[i], /*data=*/0) && !DECL_EXTERNAL (vec[i])) + { + DECL_NOT_REALLY_EXTERN (vec[i]) = 1; + DECL_EXTERNAL (vec[i]) = 1; + } + + /* Write out any globals that need to be output. */ + result = wrapup_global_declarations (vec, len); + + /* Undo the hack to DECL_EXTERNAL above. */ + for (i = 0; i < len; ++i) + if (vtable_decl_p (vec[i], /*data=*/0) + && DECL_NOT_REALLY_EXTERN (vec[i])) + { + DECL_NOT_REALLY_EXTERN (vec[i]) = 0; + DECL_EXTERNAL (vec[i]) = 0; + } + + return result; +} + + +/* For debugging. */ +static int no_print_functions = 0; +static int no_print_builtins = 0; + +void +print_binding_level (lvl) + struct binding_level *lvl; +{ + tree t; + int i = 0, len; + fprintf (stderr, " blocks="); + fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks); + fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d", + list_length (lvl->incomplete), lvl->parm_flag, lvl->keep); + if (lvl->tag_transparent) + fprintf (stderr, " tag-transparent"); + if (lvl->more_cleanups_ok) + fprintf (stderr, " more-cleanups-ok"); + if (lvl->have_cleanups) + fprintf (stderr, " have-cleanups"); + fprintf (stderr, "\n"); + if (lvl->names) + { + fprintf (stderr, " names:\t"); + /* We can probably fit 3 names to a line? */ + for (t = lvl->names; t; t = TREE_CHAIN (t)) + { + if (no_print_functions && (TREE_CODE (t) == FUNCTION_DECL)) + continue; + if (no_print_builtins + && (TREE_CODE (t) == TYPE_DECL) + && (!strcmp (DECL_SOURCE_FILE (t),""))) + continue; + + /* Function decls tend to have longer names. */ + if (TREE_CODE (t) == FUNCTION_DECL) + len = 3; + else + len = 2; + i += len; + if (i > 6) + { + fprintf (stderr, "\n\t"); + i = len; + } + print_node_brief (stderr, "", t, 0); + if (t == error_mark_node) + break; + } + if (i) + fprintf (stderr, "\n"); + } + if (lvl->tags) + { + fprintf (stderr, " tags:\t"); + i = 0; + for (t = lvl->tags; t; t = TREE_CHAIN (t)) + { + if (TREE_PURPOSE (t) == NULL_TREE) + len = 3; + else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t))) + len = 2; + else + len = 4; + i += len; + if (i > 5) + { + fprintf (stderr, "\n\t"); + i = len; + } + if (TREE_PURPOSE (t) == NULL_TREE) + { + print_node_brief (stderr, ""); + } + else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t))) + print_node_brief (stderr, "", TREE_VALUE (t), 0); + else + { + print_node_brief (stderr, ""); + } + } + if (i) + fprintf (stderr, "\n"); + } + if (lvl->class_shadowed) + { + fprintf (stderr, " class-shadowed:"); + for (t = lvl->class_shadowed; t; t = TREE_CHAIN (t)) + { + fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t))); + } + fprintf (stderr, "\n"); + } + if (lvl->type_shadowed) + { + fprintf (stderr, " type-shadowed:"); + for (t = lvl->type_shadowed; t; t = TREE_CHAIN (t)) + { + fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t))); + } + fprintf (stderr, "\n"); + } +} + +void +print_other_binding_stack (stack) + struct binding_level *stack; +{ + struct binding_level *level; + for (level = stack; level != global_binding_level; level = level->level_chain) + { + fprintf (stderr, "binding level "); + fprintf (stderr, HOST_PTR_PRINTF, level); + fprintf (stderr, "\n"); + print_binding_level (level); + } +} + +void +print_binding_stack () +{ + struct binding_level *b; + fprintf (stderr, "current_binding_level="); + fprintf (stderr, HOST_PTR_PRINTF, current_binding_level); + fprintf (stderr, "\nclass_binding_level="); + fprintf (stderr, HOST_PTR_PRINTF, class_binding_level); + fprintf (stderr, "\nglobal_binding_level="); + fprintf (stderr, HOST_PTR_PRINTF, global_binding_level); + fprintf (stderr, "\n"); + if (class_binding_level) + { + for (b = class_binding_level; b; b = b->level_chain) + if (b == current_binding_level) + break; + if (b) + b = class_binding_level; + else + b = current_binding_level; + } + else + b = current_binding_level; + print_other_binding_stack (b); + fprintf (stderr, "global:\n"); + print_binding_level (global_binding_level); +} + +/* Namespace binding access routines: The namespace_bindings field of + the identifier is polymorphic, with three possible values: + NULL_TREE, a list of CPLUS_BINDINGS, or any other tree_node + indicating the BINDING_VALUE of global_namespace. */ + +/* Check whether the a binding for the name to scope is known. + Assumes that the bindings of the name are already a list + of bindings. Returns the binding found, or NULL_TREE. */ + +static tree +find_binding (name, scope) + tree name; + tree scope; +{ + tree iter, prev = NULL_TREE; + + scope = ORIGINAL_NAMESPACE (scope); + + for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter; + iter = TREE_CHAIN (iter)) + { + my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374); + if (BINDING_SCOPE (iter) == scope) + { + /* Move binding found to the fron of the list, so + subsequent lookups will find it faster. */ + if (prev) + { + TREE_CHAIN (prev) = TREE_CHAIN (iter); + TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name); + IDENTIFIER_NAMESPACE_BINDINGS (name) = iter; + } + return iter; + } + prev = iter; + } + return NULL_TREE; +} + +/* Always returns a binding for name in scope. If the + namespace_bindings is not a list, convert it to one first. + If no binding is found, make a new one. */ + +tree +binding_for_name (name, scope) + tree name; + tree scope; +{ + tree b = IDENTIFIER_NAMESPACE_BINDINGS (name); + tree result; + + scope = ORIGINAL_NAMESPACE (scope); + + if (b && TREE_CODE (b) != CPLUS_BINDING) + { + /* Get rid of optimization for global scope. */ + IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE; + BINDING_VALUE (binding_for_name (name, global_namespace)) = b; + b = IDENTIFIER_NAMESPACE_BINDINGS (name); + } + if (b && (result = find_binding (name, scope))) + return result; + /* Not found, make a new permanent one. */ + push_obstacks (&permanent_obstack, &permanent_obstack); + result = make_node (CPLUS_BINDING); + TREE_CHAIN (result) = b; + IDENTIFIER_NAMESPACE_BINDINGS (name) = result; + BINDING_SCOPE (result) = scope; + BINDING_TYPE (result) = NULL_TREE; + BINDING_VALUE (result) = NULL_TREE; + pop_obstacks (); + return result; +} + +/* Return the binding value for name in scope, considering that + namespace_binding may or may not be a list of CPLUS_BINDINGS. */ + +tree +namespace_binding (name, scope) + tree name; + tree scope; +{ + tree b = IDENTIFIER_NAMESPACE_BINDINGS (name); + if (b == NULL_TREE) + return NULL_TREE; + if (scope == NULL_TREE) + scope = global_namespace; + if (TREE_CODE (b) != CPLUS_BINDING) + return (scope == global_namespace) ? b : NULL_TREE; + name = find_binding (name,scope); + if (name == NULL_TREE) + return name; + return BINDING_VALUE (name); +} + +/* Set the binding value for name in scope. If modifying the binding + of global_namespace is attempted, try to optimize it. */ + +void +set_namespace_binding (name, scope, val) + tree name; + tree scope; + tree val; +{ + tree b; + + if (scope == NULL_TREE) + scope = global_namespace; + + if (scope == global_namespace) + { + b = IDENTIFIER_NAMESPACE_BINDINGS (name); + if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING) + { + IDENTIFIER_NAMESPACE_BINDINGS (name) = val; + return; + } + } + b = binding_for_name (name, scope); + BINDING_VALUE (b) = val; +} + +/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we + select a name that is unique to this compilation unit. */ + +void +push_namespace (name) + tree name; +{ + tree d = NULL_TREE; + int need_new = 1; + int implicit_use = 0; + int global = 0; + if (!global_namespace) + { + /* This must be ::. */ + my_friendly_assert (name == get_identifier ("::"), 377); + global = 1; + } + else if (!name) + { + /* The name of anonymous namespace is unique for the translation + unit. */ + if (!anonymous_namespace_name) + anonymous_namespace_name = get_file_function_name ('N'); + name = anonymous_namespace_name; + d = IDENTIFIER_NAMESPACE_VALUE (name); + if (d) + /* Reopening anonymous namespace. */ + need_new = 0; + implicit_use = 1; + } + else if (current_namespace == global_namespace + && name == DECL_NAME (std_node)) + { + in_std++; + return; + } + else + { + /* Check whether this is an extended namespace definition. */ + d = IDENTIFIER_NAMESPACE_VALUE (name); + if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL) + { + need_new = 0; + if (DECL_NAMESPACE_ALIAS (d)) + { + cp_error ("namespace alias `%D' not allowed here, assuming `%D'", + d, DECL_NAMESPACE_ALIAS (d)); + d = DECL_NAMESPACE_ALIAS (d); + } + } + } + + if (need_new) + { + /* Make a new namespace, binding the name to it. */ + d = build_lang_decl (NAMESPACE_DECL, name, void_type_node); + /* The global namespace is not pushed, and the global binding + level is set elsewhere. */ + if (!global) + { + d = pushdecl (d); + pushlevel (0); + declare_namespace_level (); + NAMESPACE_LEVEL (d) = current_binding_level; + } + } + else + resume_binding_level (NAMESPACE_LEVEL (d)); + + if (implicit_use) + do_using_directive (d); + /* Enter the name space. */ + current_namespace = d; +} + +/* Pop from the scope of the current namespace. */ + +void +pop_namespace () +{ + if (current_namespace == global_namespace) + { + my_friendly_assert (in_std>0, 980421); + in_std--; + return; + } + current_namespace = CP_DECL_CONTEXT (current_namespace); + /* The binding level is not popped, as it might be re-opened later. */ + suspend_binding_level (); +} + + +/* Subroutines for reverting temporarily to top-level for instantiation + of templates and such. We actually need to clear out the class- and + local-value slots of all identifiers, so that only the global values + are at all visible. Simply setting current_binding_level to the global + scope isn't enough, because more binding levels may be pushed. */ +struct saved_scope { + struct binding_level *old_binding_level; + tree old_bindings; + tree old_namespace; + struct saved_scope *prev; + tree class_name, class_type; + tree access_specifier; + tree function_decl; + struct binding_level *class_bindings; + tree *lang_base, *lang_stack, lang_name; + int lang_stacksize; + int minimal_parse_mode; + tree last_function_parms; + tree template_parms; + HOST_WIDE_INT processing_template_decl; + tree previous_class_type, previous_class_values; + int processing_specialization; + int processing_explicit_instantiation; + char *class_cache_firstobj; +}; +static struct saved_scope *current_saved_scope; + +/* A chain of the binding vecs created by store_bindings. We create a + whole bunch of these during compilation, on permanent_obstack, so we + can't just throw them away. */ +static tree free_binding_vecs; + +static tree +store_bindings (names, old_bindings) + tree names, old_bindings; +{ + tree t; + for (t = names; t; t = TREE_CHAIN (t)) + { + tree binding, t1, id; + + if (TREE_CODE (t) == TREE_LIST) + id = TREE_PURPOSE (t); + else + id = DECL_NAME (t); + + if (!id + /* Note that we may have an IDENTIFIER_CLASS_VALUE even when + we have no IDENTIFIER_BINDING if we have left the class + scope, but cached the class-level declarations. */ + || !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id))) + continue; + + for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1)) + if (TREE_VEC_ELT (t1, 0) == id) + goto skip_it; + + if (free_binding_vecs) + { + binding = free_binding_vecs; + free_binding_vecs = TREE_CHAIN (free_binding_vecs); + } + else + binding = make_tree_vec (4); + + if (id) + { + my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135); + TREE_VEC_ELT (binding, 0) = id; + TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id); + TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id); + TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id); + IDENTIFIER_BINDING (id) = NULL_TREE; + IDENTIFIER_CLASS_VALUE (id) = NULL_TREE; + } + TREE_CHAIN (binding) = old_bindings; + old_bindings = binding; + skip_it: + ; + } + return old_bindings; +} + +void +maybe_push_to_top_level (pseudo) + int pseudo; +{ + extern int current_lang_stacksize; + struct saved_scope *s + = (struct saved_scope *) xmalloc (sizeof (struct saved_scope)); + struct binding_level *b = current_binding_level; + tree old_bindings = NULL_TREE; + + push_cp_function_context (NULL_TREE); + + if (previous_class_type) + old_bindings = store_bindings (previous_class_values, old_bindings); + + /* Have to include global_binding_level, because class-level decls + aren't listed anywhere useful. */ + for (; b; b = b->level_chain) + { + tree t; + + /* Template IDs are inserted into the global level. If they were + inserted into namespace level, finish_file wouldn't find them + when doing pending instantiations. Therefore, don't stop at + namespace level, but continue until :: . */ + if (b == global_binding_level || (pseudo && b->pseudo_global)) + break; + + old_bindings = store_bindings (b->names, old_bindings); + /* We also need to check class_shadowed to save class-level type + bindings, since pushclass doesn't fill in b->names. */ + if (b->parm_flag == 2) + old_bindings = store_bindings (b->class_shadowed, old_bindings); + + /* Unwind type-value slots back to top level. */ + for (t = b->type_shadowed; t; t = TREE_CHAIN (t)) + SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t)); + } + + s->old_binding_level = current_binding_level; + current_binding_level = b; + + s->old_namespace = current_namespace; + s->class_name = current_class_name; + s->class_type = current_class_type; + s->access_specifier = current_access_specifier; + s->function_decl = current_function_decl; + s->class_bindings = class_binding_level; + s->lang_stack = current_lang_stack; + s->lang_base = current_lang_base; + s->lang_stacksize = current_lang_stacksize; + s->lang_name = current_lang_name; + s->minimal_parse_mode = minimal_parse_mode; + s->last_function_parms = last_function_parms; + s->template_parms = current_template_parms; + s->processing_template_decl = processing_template_decl; + s->previous_class_type = previous_class_type; + s->previous_class_values = previous_class_values; + s->class_cache_firstobj = class_cache_firstobj; + s->processing_specialization = processing_specialization; + s->processing_explicit_instantiation = processing_explicit_instantiation; + + current_class_name = current_class_type = NULL_TREE; + current_function_decl = NULL_TREE; + class_binding_level = (struct binding_level *)0; + current_lang_stacksize = 10; + current_lang_stack = current_lang_base + = (tree *) xmalloc (current_lang_stacksize * sizeof (tree)); + current_lang_name = lang_name_cplusplus; + strict_prototype = strict_prototypes_lang_cplusplus; + named_labels = NULL_TREE; + shadowed_labels = NULL_TREE; + minimal_parse_mode = 0; + previous_class_type = previous_class_values = NULL_TREE; + class_cache_firstobj = 0; + processing_specialization = 0; + processing_explicit_instantiation = 0; + current_template_parms = NULL_TREE; + processing_template_decl = 0; + current_namespace = global_namespace; + + s->prev = current_saved_scope; + s->old_bindings = old_bindings; + current_saved_scope = s; + + push_obstacks (&permanent_obstack, &permanent_obstack); +} + +void +push_to_top_level () +{ + maybe_push_to_top_level (0); +} + +void +pop_from_top_level () +{ + extern int current_lang_stacksize; + struct saved_scope *s = current_saved_scope; + tree t; + + /* Clear out class-level bindings cache. */ + if (previous_class_type) + invalidate_class_lookup_cache (); + + pop_obstacks (); + + current_binding_level = s->old_binding_level; + current_saved_scope = s->prev; + for (t = s->old_bindings; t; ) + { + tree save = t; + tree id = TREE_VEC_ELT (t, 0); + if (id) + { + SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1)); + IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2); + IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3); + } + t = TREE_CHAIN (t); + TREE_CHAIN (save) = free_binding_vecs; + free_binding_vecs = save; + } + current_namespace = s->old_namespace; + current_class_name = s->class_name; + current_class_type = s->class_type; + current_access_specifier = s->access_specifier; + current_function_decl = s->function_decl; + class_binding_level = s->class_bindings; + free (current_lang_base); + current_lang_base = s->lang_base; + current_lang_stack = s->lang_stack; + current_lang_name = s->lang_name; + current_lang_stacksize = s->lang_stacksize; + if (current_lang_name == lang_name_cplusplus) + strict_prototype = strict_prototypes_lang_cplusplus; + else if (current_lang_name == lang_name_c) + strict_prototype = strict_prototypes_lang_c; + minimal_parse_mode = s->minimal_parse_mode; + last_function_parms = s->last_function_parms; + current_template_parms = s->template_parms; + processing_template_decl = s->processing_template_decl; + previous_class_type = s->previous_class_type; + previous_class_values = s->previous_class_values; + processing_specialization = s->processing_specialization; + processing_explicit_instantiation = s->processing_explicit_instantiation; + class_cache_firstobj = s->class_cache_firstobj; + + free (s); + + pop_cp_function_context (NULL_TREE); +} + +/* Push a definition of struct, union or enum tag "name". + into binding_level "b". "type" should be the type node, + We assume that the tag "name" is not already defined. + + Note that the definition may really be just a forward reference. + In that case, the TYPE_SIZE will be a NULL_TREE. + + C++ gratuitously puts all these tags in the name space. */ + +/* When setting the IDENTIFIER_TYPE_VALUE field of an identifier ID, + record the shadowed value for this binding contour. TYPE is + the type that ID maps to. */ + +static void +set_identifier_type_value_with_scope (id, type, b) + tree id; + tree type; + struct binding_level *b; +{ + if (!b->namespace_p) + { + /* Shadow the marker, not the real thing, so that the marker + gets restored later. */ + tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id); + b->type_shadowed + = tree_cons (id, old_type_value, b->type_shadowed); + } + else + { + tree binding = binding_for_name (id, current_namespace); + BINDING_TYPE (binding) = type; + /* Store marker instead of real type. */ + type = global_type_node; + } + SET_IDENTIFIER_TYPE_VALUE (id, type); +} + +/* As set_identifier_type_value_with_scope, but using current_binding_level. */ + +void +set_identifier_type_value (id, type) + tree id; + tree type; +{ + set_identifier_type_value_with_scope (id, type, current_binding_level); +} + +/* Return the type associated with id. */ + +tree +identifier_type_value (id) + tree id; +{ + /* There is no type with that name, anywhere. */ + if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE) + return NULL_TREE; + /* This is not the type marker, but the real thing. */ + if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node) + return REAL_IDENTIFIER_TYPE_VALUE (id); + /* Have to search for it. It must be on the global level, now. + Ask lookup_name not to return non-types. */ + id = lookup_name_real (id, 2, 1, 0); + if (id) + return TREE_TYPE (id); + return NULL_TREE; +} + +/* Pop off extraneous binding levels left over due to syntax errors. + + We don't pop past namespaces, as they might be valid. */ + +void +pop_everything () +{ +#ifdef DEBUG_CP_BINDING_LEVELS + fprintf (stderr, "XXX entering pop_everything ()\n"); +#endif + while (!toplevel_bindings_p ()) + { + if (current_binding_level->parm_flag == 2) + pop_nested_class (); + else + poplevel (0, 0, 0); + } +#ifdef DEBUG_CP_BINDING_LEVELS + fprintf (stderr, "XXX leaving pop_everything ()\n"); +#endif +} + +/* The type TYPE is being declared. If it is a class template, or a + specialization of a class template, do any processing required and + perform error-checking. If IS_FRIEND is non-zero, this TYPE is + being declared a friend. B is the binding level at which this TYPE + should be bound. + + Returns the TYPE_DECL for TYPE, which may have been altered by this + processing. */ + +static tree +maybe_process_template_type_declaration (type, globalize, b) + tree type; + int globalize; + struct binding_level* b; +{ + tree decl = TYPE_NAME (type); + + if (processing_template_parmlist) + /* You can't declare a new template type in a template parameter + list. But, you can declare a non-template type: + + template struct S; + + is a forward-declaration of `A'. */ + ; + else + { + maybe_check_template_type (type); + + my_friendly_assert (IS_AGGR_TYPE (type) + || TREE_CODE (type) == ENUMERAL_TYPE, 0); + + + if (/* If !GLOBALIZE then we are looking at a definition. + It may not be a primary template. (For example, in: + + template + struct S1 { class S2 {}; } + + we have to push_template_decl for S2.) */ + (processing_template_decl && !globalize) + /* If we are declaring a friend template class, we will + have GLOBALIZE set, since something like: + + template + struct S1 { + template + friend class S2; + }; + + declares S2 to be at global scope. */ + || PROCESSING_REAL_TEMPLATE_DECL_P ()) + { + /* This may change after the call to + push_template_decl_real, but we want the original value. */ + tree name = DECL_NAME (decl); + + decl = push_template_decl_real (decl, globalize); + /* If the current binding level is the binding level for the + template parameters (see the comment in + begin_template_parm_list) and the enclosing level is a class + scope, and we're not looking at a friend, push the + declaration of the member class into the class scope. In the + friend case, push_template_decl will already have put the + friend into global scope, if appropriate. */ + if (TREE_CODE (type) != ENUMERAL_TYPE + && !globalize && b->pseudo_global + && b->level_chain->parm_flag == 2) + { + finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type)); + /* Put this tag on the list of tags for the class, since + that won't happen below because B is not the class + binding level, but is instead the pseudo-global level. */ + b->level_chain->tags = + saveable_tree_cons (name, type, b->level_chain->tags); + if (TYPE_SIZE (current_class_type) == NULL_TREE) + CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags; + } + } + } + + return decl; +} + +/* Push a tag name NAME for struct/class/union/enum type TYPE. + Normally put it into the inner-most non-tag-transparent scope, + but if GLOBALIZE is true, put it in the inner-most non-class scope. + The latter is needed for implicit declarations. */ + +void +pushtag (name, type, globalize) + tree name, type; + int globalize; +{ + register struct binding_level *b; + + b = current_binding_level; + while (b->tag_transparent + || (globalize && b->parm_flag == 2)) + b = b->level_chain; + + if (toplevel_bindings_p ()) + b->tags = perm_tree_cons (name, type, b->tags); + else + b->tags = saveable_tree_cons (name, type, b->tags); + + if (name) + { + /* Do C++ gratuitous typedefing. */ + if (IDENTIFIER_TYPE_VALUE (name) != type) + { + register tree d = NULL_TREE; + int newdecl = 0, in_class = 0; + tree context; + tree c_decl = NULL_TREE; + + context = type ? TYPE_CONTEXT (type) : NULL_TREE; + if (! context) + { + tree cs = current_scope (); + + if (! globalize) + context = cs; + else if (cs != NULL_TREE + && TREE_CODE_CLASS (TREE_CODE (cs)) == 't') + /* When declaring a friend class of a local class, we want + to inject the newly named class into the scope + containing the local class, not the namespace scope. */ + context = hack_decl_function_context (get_type_decl (cs)); + } + if (context) + c_decl = TREE_CODE (context) == FUNCTION_DECL + ? context : TYPE_MAIN_DECL (context); + + if (!context) + context = current_namespace; + + if ((b->pseudo_global && b->level_chain->parm_flag == 2) + || b->parm_flag == 2) + in_class = 1; + else + d = lookup_nested_type (type, c_decl); + + if (d == NULL_TREE) + { + newdecl = 1; + d = build_decl (TYPE_DECL, name, type); + if (current_lang_name == lang_name_java) + TYPE_FOR_JAVA (type) = 1; + SET_DECL_ARTIFICIAL (d); + if (! in_class) + set_identifier_type_value_with_scope (name, type, b); + } + else + d = TYPE_MAIN_DECL (d); + + TYPE_NAME (type) = d; + DECL_CONTEXT (d) = FROB_CONTEXT (context); + + d = maybe_process_template_type_declaration (type, + globalize, b); + + if (b->parm_flag == 2) + { + if (newdecl && !PROCESSING_REAL_TEMPLATE_DECL_P ()) + /* Put this TYPE_DECL on the TYPE_FIELDS list for the + class. But if it's a member template class, we + want the TEMPLATE_DECL, not the TYPE_DECL, so this + is done later. */ + finish_member_declaration (d); + else + pushdecl_class_level (d); + } + else + d = pushdecl_with_scope (d, b); + + if (newdecl) + { + if (ANON_AGGRNAME_P (name)) + DECL_IGNORED_P (d) = 1; + + TYPE_CONTEXT (type) = DECL_CONTEXT (d); + DECL_ASSEMBLER_NAME (d) = DECL_NAME (d); + if (!uses_template_parms (type)) + DECL_ASSEMBLER_NAME (d) + = get_identifier (build_overload_name (type, 1, 1)); + } + } + if (b->parm_flag == 2) + { + if (TYPE_SIZE (current_class_type) == NULL_TREE) + CLASSTYPE_TAGS (current_class_type) = b->tags; + } + } + + if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) + /* Use the canonical TYPE_DECL for this node. */ + TYPE_STUB_DECL (type) = TYPE_NAME (type); + else + { + /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE + will be the tagged type we just added to the current + binding level. This fake NULL-named TYPE_DECL node helps + dwarfout.c to know when it needs to output a + representation of a tagged type, and it also gives us a + convenient place to record the "scope start" address for + the tagged type. */ + + tree d = build_decl (TYPE_DECL, NULL_TREE, type); + TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b); + } +} + +/* Counter used to create anonymous type names. */ + +static int anon_cnt = 0; + +/* Return an IDENTIFIER which can be used as a name for + anonymous structs and unions. */ + +tree +make_anon_name () +{ + char buf[32]; + + sprintf (buf, ANON_AGGRNAME_FORMAT, anon_cnt++); + return get_identifier (buf); +} + +/* Clear the TREE_PURPOSE slot of tags which have anonymous typenames. + This keeps dbxout from getting confused. */ + +void +clear_anon_tags () +{ + register struct binding_level *b; + register tree tags; + static int last_cnt = 0; + + /* Fast out if no new anon names were declared. */ + if (last_cnt == anon_cnt) + return; + + b = current_binding_level; + while (b->tag_transparent) + b = b->level_chain; + tags = b->tags; + while (tags) + { + /* A NULL purpose means we have already processed all tags + from here to the end of the list. */ + if (TREE_PURPOSE (tags) == NULL_TREE) + break; + if (ANON_AGGRNAME_P (TREE_PURPOSE (tags))) + TREE_PURPOSE (tags) = NULL_TREE; + tags = TREE_CHAIN (tags); + } + last_cnt = anon_cnt; +} + +/* Subroutine of duplicate_decls: return truthvalue of whether + or not types of these decls match. + + For C++, we must compare the parameter list so that `int' can match + `int&' in a parameter position, but `int&' is not confused with + `const int&'. */ + +int +decls_match (newdecl, olddecl) + tree newdecl, olddecl; +{ + int types_match; + + if (newdecl == olddecl) + return 1; + + 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); + tree p1 = TYPE_ARG_TYPES (f1); + tree p2 = TYPE_ARG_TYPES (f2); + + if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl) + && ! (DECL_LANGUAGE (newdecl) == lang_c + && DECL_LANGUAGE (olddecl) == lang_c)) + return 0; + + /* When we parse a static member function definition, + we put together a FUNCTION_DECL which thinks its type + is METHOD_TYPE. Change that to FUNCTION_TYPE, and + proceed. */ + if (TREE_CODE (f1) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (olddecl)) + revert_static_member_fn (&newdecl, &f1, &p1); + else if (TREE_CODE (f2) == METHOD_TYPE + && DECL_STATIC_FUNCTION_P (newdecl)) + revert_static_member_fn (&olddecl, &f2, &p2); + + /* Here we must take care of the case where new default + parameters are specified. Also, warn if an old + declaration becomes ambiguous because default + parameters may cause the two to be ambiguous. */ + if (TREE_CODE (f1) != TREE_CODE (f2)) + { + if (TREE_CODE (f1) == OFFSET_TYPE) + cp_compiler_error ("`%D' redeclared as member function", newdecl); + else + cp_compiler_error ("`%D' redeclared as non-member function", newdecl); + return 0; + } + + if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2))) + { + if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c + && p2 == NULL_TREE) + { + types_match = self_promoting_args_p (p1); + if (p1 == void_list_node) + TREE_TYPE (newdecl) = TREE_TYPE (olddecl); + } + else if (!strict_prototypes_lang_c && DECL_LANGUAGE (olddecl)==lang_c + && DECL_LANGUAGE (newdecl) == lang_c && p1 == NULL_TREE) + { + types_match = self_promoting_args_p (p2); + TREE_TYPE (newdecl) = TREE_TYPE (olddecl); + } + else + types_match = compparms (p1, p2); + } + else + types_match = 0; + } + else if (TREE_CODE (newdecl) == TEMPLATE_DECL) + { + if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl), + DECL_TEMPLATE_PARMS (olddecl))) + return 0; + + if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL) + types_match = 1; + else + types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl), + DECL_TEMPLATE_RESULT (newdecl)); + } + else + { + if (TREE_TYPE (newdecl) == error_mark_node) + types_match = TREE_TYPE (olddecl) == error_mark_node; + else if (TREE_TYPE (olddecl) == NULL_TREE) + types_match = TREE_TYPE (newdecl) == NULL_TREE; + else if (TREE_TYPE (newdecl) == NULL_TREE) + types_match = 0; + else + types_match = comptypes (TREE_TYPE (newdecl), + TREE_TYPE (olddecl), + COMPARE_REDECLARATION); + } + + return types_match; +} + +/* If NEWDECL is `static' and an `extern' was seen previously, + warn about it. (OLDDECL may be NULL_TREE; NAME contains + information about previous usage as an `extern'.) + + Note that this does not apply to the C++ case of declaring + a variable `extern const' and then later `const'. + + Don't complain about built-in functions, since they are beyond + the user's control. */ + +static void +warn_extern_redeclared_static (newdecl, olddecl) + tree newdecl, olddecl; +{ + tree name; + + static const char *explicit_extern_static_warning + = "`%D' was declared `extern' and later `static'"; + static const char *implicit_extern_static_warning + = "`%D' was declared implicitly `extern' and later `static'"; + + if (TREE_CODE (newdecl) == TYPE_DECL) + return; + + name = DECL_ASSEMBLER_NAME (newdecl); + if (TREE_PUBLIC (name) && DECL_THIS_STATIC (newdecl)) + { + /* It's okay to redeclare an ANSI built-in function as static, + or to declare a non-ANSI built-in function as anything. */ + if (! (TREE_CODE (newdecl) == FUNCTION_DECL + && olddecl != NULL_TREE + && TREE_CODE (olddecl) == FUNCTION_DECL + && (DECL_BUILT_IN (olddecl) + || DECL_BUILT_IN_NONANSI (olddecl)))) + { + cp_pedwarn (IDENTIFIER_IMPLICIT_DECL (name) + ? implicit_extern_static_warning + : explicit_extern_static_warning, newdecl); + if (olddecl != NULL_TREE) + cp_pedwarn_at ("previous declaration of `%D'", olddecl); + } + } +} + +/* Handle when a new declaration NEWDECL has the same name as an old + one OLDDECL in the same binding contour. Prints an error message + if appropriate. + + If safely possible, alter OLDDECL to look like NEWDECL, and return 1. + Otherwise, return 0. */ + +int +duplicate_decls (newdecl, olddecl) + tree newdecl, olddecl; +{ + extern struct obstack permanent_obstack; + unsigned olddecl_uid = DECL_UID (olddecl); + int olddecl_friend = 0, types_match = 0; + int new_defines_function = 0; + + if (newdecl == olddecl) + return 1; + + types_match = decls_match (newdecl, olddecl); + + /* If either the type of the new decl or the type of the old decl is an + error_mark_node, then that implies that we have already issued an + error (earlier) for some bogus type specification, and in that case, + it is rather pointless to harass the user with yet more error message + about the same declaration, so just pretend the types match here. */ + if (TREE_TYPE (newdecl) == error_mark_node + || TREE_TYPE (olddecl) == error_mark_node) + types_match = 1; + + /* Check for redeclaration and other discrepancies. */ + if (TREE_CODE (olddecl) == FUNCTION_DECL + && DECL_ARTIFICIAL (olddecl) + && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl))) + { + /* If you declare a built-in or predefined function name as static, + the old definition is overridden, but optionally warn this was a + bad choice of name. Ditto for overloads. */ + if (! TREE_PUBLIC (newdecl) + || (TREE_CODE (newdecl) == FUNCTION_DECL + && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))) + { + if (warn_shadow) + cp_warning ("shadowing %s function `%#D'", + DECL_BUILT_IN (olddecl) ? "built-in" : "library", + olddecl); + /* Discard the old built-in function. */ + return 0; + } + else if (! types_match) + { + if (TREE_CODE (newdecl) != FUNCTION_DECL) + { + /* If the built-in is not ansi, then programs can override + it even globally without an error. */ + if (! DECL_BUILT_IN (olddecl)) + cp_warning ("library function `%#D' redeclared as non-function `%#D'", + olddecl, newdecl); + else + { + cp_error ("declaration of `%#D'", newdecl); + cp_error ("conflicts with built-in declaration `%#D'", + olddecl); + } + return 0; + } + + cp_warning ("declaration of `%#D'", newdecl); + cp_warning ("conflicts with built-in declaration `%#D'", + olddecl); + } + } + else if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) + { + if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl) + && TREE_CODE (newdecl) != TYPE_DECL + && ! (TREE_CODE (newdecl) == TEMPLATE_DECL + && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)) + || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl) + && TREE_CODE (olddecl) != TYPE_DECL + && ! (TREE_CODE (olddecl) == TEMPLATE_DECL + && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) + == TYPE_DECL)))) + { + /* We do nothing special here, because C++ does such nasty + things with TYPE_DECLs. Instead, just let the TYPE_DECL + get shadowed, and know that if we need to find a TYPE_DECL + for a given name, we can look in the IDENTIFIER_TYPE_VALUE + slot of the identifier. */ + return 0; + } + + if ((TREE_CODE (newdecl) == FUNCTION_DECL + && DECL_FUNCTION_TEMPLATE_P (olddecl)) + || (TREE_CODE (olddecl) == FUNCTION_DECL + && DECL_FUNCTION_TEMPLATE_P (newdecl))) + return 0; + + cp_error ("`%#D' redeclared as different kind of symbol", newdecl); + if (TREE_CODE (olddecl) == TREE_LIST) + olddecl = TREE_VALUE (olddecl); + cp_error_at ("previous declaration of `%#D'", olddecl); + + /* New decl is completely inconsistent with the old one => + tell caller to replace the old one. */ + + return 0; + } + else if (!types_match) + { + if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl)) + /* These are certainly not duplicate declarations; they're + from different scopes. */ + return 0; + + if (TREE_CODE (newdecl) == TEMPLATE_DECL) + { + /* The name of a class template may not be declared to refer to + any other template, class, function, object, namespace, value, + or type in the same scope. */ + if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL + || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL) + { + cp_error ("declaration of template `%#D'", newdecl); + cp_error_at ("conflicts with previous declaration `%#D'", + olddecl); + } + else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL + && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL + && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))), + TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl)))) + && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl), + DECL_TEMPLATE_PARMS (olddecl))) + { + cp_error ("new declaration `%#D'", newdecl); + cp_error_at ("ambiguates old declaration `%#D'", olddecl); + } + return 0; + } + if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + if (DECL_LANGUAGE (newdecl) == lang_c + && DECL_LANGUAGE (olddecl) == lang_c) + { + cp_error ("declaration of C function `%#D' conflicts with", + newdecl); + cp_error_at ("previous declaration `%#D' here", olddecl); + } + else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), + TYPE_ARG_TYPES (TREE_TYPE (olddecl)))) + { + cp_error ("new declaration `%#D'", newdecl); + cp_error_at ("ambiguates old declaration `%#D'", olddecl); + } + else + return 0; + } + + /* Already complained about this, so don't do so again. */ + else if (current_class_type == NULL_TREE + || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type) + { + cp_error ("conflicting types for `%#D'", newdecl); + cp_error_at ("previous declaration as `%#D'", olddecl); + } + } + else if (TREE_CODE (newdecl) == FUNCTION_DECL + && ((DECL_TEMPLATE_SPECIALIZATION (olddecl) + && (!DECL_TEMPLATE_INFO (newdecl) + || (DECL_TI_TEMPLATE (newdecl) + != DECL_TI_TEMPLATE (olddecl)))) + || (DECL_TEMPLATE_SPECIALIZATION (newdecl) + && (!DECL_TEMPLATE_INFO (olddecl) + || (DECL_TI_TEMPLATE (olddecl) + != DECL_TI_TEMPLATE (newdecl)))))) + /* It's OK to have a template specialization and a non-template + with the same type, or to have specializations of two + different templates with the same type. Note that if one is a + specialization, and the other is an instantiation of the same + template, that we do not exit at this point. That situation + can occur if we instantiate a template class, and then + specialize one of its methods. This situation is legal, but + the declarations must be merged in the usual way. */ + return 0; + else if (TREE_CODE (newdecl) == FUNCTION_DECL + && ((DECL_TEMPLATE_INSTANTIATION (olddecl) + && !DECL_USE_TEMPLATE (newdecl)) + || (DECL_TEMPLATE_INSTANTIATION (newdecl) + && !DECL_USE_TEMPLATE (olddecl)))) + /* One of the declarations is a template instantiation, and the + other is not a template at all. That's OK. */ + return 0; + else if (TREE_CODE (newdecl) == NAMESPACE_DECL + && DECL_NAMESPACE_ALIAS (newdecl) + && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl)) + /* Redeclaration of namespace alias, ignore it. */ + return 1; + else + { + const char *errmsg = redeclaration_error_message (newdecl, olddecl); + if (errmsg) + { + cp_error (errmsg, newdecl); + if (DECL_NAME (olddecl) != NULL_TREE) + cp_error_at ((DECL_INITIAL (olddecl) + && namespace_bindings_p ()) + ? "`%#D' previously defined here" + : "`%#D' previously declared here", olddecl); + } + else if (TREE_CODE (olddecl) == FUNCTION_DECL + && DECL_INITIAL (olddecl) != NULL_TREE + && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE + && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE) + { + /* Prototype decl follows defn w/o prototype. */ + cp_warning_at ("prototype for `%#D'", newdecl); + cp_warning_at ("follows non-prototype definition here", olddecl); + } + else if (TREE_CODE (olddecl) == FUNCTION_DECL + && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl)) + { + /* extern "C" int foo (); + int foo () { bar (); } + is OK. */ + if (current_lang_stack == current_lang_base) + DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl); + else + { + cp_error_at ("previous declaration of `%#D' with %L linkage", + olddecl, DECL_LANGUAGE (olddecl)); + cp_error ("conflicts with new declaration with %L linkage", + DECL_LANGUAGE (newdecl)); + } + } + + if (DECL_LANG_SPECIFIC (olddecl) && DECL_USE_TEMPLATE (olddecl)) + ; + else if (TREE_CODE (olddecl) == FUNCTION_DECL) + { + tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); + tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); + int i = 1; + + if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE) + t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2); + + for (; t1 && t1 != void_list_node; + t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++) + if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) + { + if (1 == simple_cst_equal (TREE_PURPOSE (t1), + TREE_PURPOSE (t2))) + { + if (pedantic) + { + cp_pedwarn ("default argument given for parameter %d of `%#D'", + i, newdecl); + cp_pedwarn_at ("after previous specification in `%#D'", + olddecl); + } + } + else + { + cp_error ("default argument given for parameter %d of `%#D'", + i, newdecl); + cp_error_at ("after previous specification in `%#D'", + olddecl); + } + } + + if (DECL_THIS_INLINE (newdecl) && ! DECL_THIS_INLINE (olddecl) + && TREE_ADDRESSABLE (olddecl) && warn_inline) + { + cp_warning ("`%#D' was used before it was declared inline", + newdecl); + cp_warning_at ("previous non-inline declaration here", + olddecl); + } + } + } + + /* If new decl is `static' and an `extern' was seen previously, + warn about it. */ + warn_extern_redeclared_static (newdecl, olddecl); + + /* We have committed to returning 1 at this point. */ + if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + /* Now that functions must hold information normally held + by field decls, there is extra work to do so that + declaration information does not get destroyed during + definition. */ + if (DECL_VINDEX (olddecl)) + DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl); + if (DECL_CONTEXT (olddecl)) + DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); + if (DECL_CLASS_CONTEXT (olddecl)) + DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl); + if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0) + DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl); + DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl); + DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); + DECL_ABSTRACT_VIRTUAL_P (newdecl) |= DECL_ABSTRACT_VIRTUAL_P (olddecl); + DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl); + DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl); + new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE; + + /* Optionally warn about more than one declaration for the same + name, but don't warn about a function declaration followed by a + definition. */ + if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl) + && !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE) + /* Don't warn about extern decl followed by definition. */ + && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl)) + /* Don't warn about friends, let add_friend take care of it. */ + && ! DECL_FRIEND_P (newdecl)) + { + cp_warning ("redundant redeclaration of `%D' in same scope", newdecl); + cp_warning_at ("previous declaration of `%D'", olddecl); + } + } + + /* Deal with C++: must preserve virtual function table size. */ + if (TREE_CODE (olddecl) == TYPE_DECL) + { + register tree newtype = TREE_TYPE (newdecl); + register tree oldtype = TREE_TYPE (olddecl); + + if (newtype != error_mark_node && oldtype != error_mark_node + && TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype)) + { + CLASSTYPE_VSIZE (newtype) = CLASSTYPE_VSIZE (oldtype); + CLASSTYPE_FRIEND_CLASSES (newtype) + = CLASSTYPE_FRIEND_CLASSES (oldtype); + } + } + + /* Copy all the DECL_... slots specified in the new decl + except for any that we copy here from the old type. */ + DECL_MACHINE_ATTRIBUTES (newdecl) + = merge_machine_decl_attributes (olddecl, newdecl); + + if (TREE_CODE (newdecl) == TEMPLATE_DECL) + { + if (! duplicate_decls (DECL_TEMPLATE_RESULT (newdecl), + DECL_TEMPLATE_RESULT (olddecl))) + cp_error ("invalid redeclaration of %D", newdecl); + TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl)); + DECL_TEMPLATE_SPECIALIZATIONS (olddecl) + = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl), + DECL_TEMPLATE_SPECIALIZATIONS (newdecl)); + + return 1; + } + + if (types_match) + { + /* Automatically handles default parameters. */ + tree oldtype = TREE_TYPE (olddecl); + tree newtype; + + /* Make sure we put the new type in the same obstack as the old one. */ + if (oldtype) + push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype)); + else + { + push_obstacks_nochange (); + end_temporary_allocation (); + } + + /* Merge the data types specified in the two decls. */ + newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); + + if (TREE_CODE (newdecl) == VAR_DECL) + DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl); + /* Do this after calling `common_type' so that default + parameters don't confuse us. */ + else if (TREE_CODE (newdecl) == FUNCTION_DECL + && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)) + != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)))) + { + TREE_TYPE (newdecl) = build_exception_variant (newtype, + TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))); + TREE_TYPE (olddecl) = build_exception_variant (newtype, + TYPE_RAISES_EXCEPTIONS (oldtype)); + + if ((pedantic || (! DECL_IN_SYSTEM_HEADER (olddecl) + && ! DECL_IN_SYSTEM_HEADER (newdecl))) + && DECL_SOURCE_LINE (olddecl) != 0 + && flag_exceptions + && ! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl))) + { + cp_pedwarn ("declaration of `%D' throws different exceptions", + newdecl); + cp_pedwarn_at ("previous declaration here", olddecl); + } + } + TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype; + + /* Lay the type out, unless already done. */ + if (! same_type_p (newtype, oldtype) + && TREE_TYPE (newdecl) != error_mark_node + && !(processing_template_decl && uses_template_parms (newdecl))) + layout_type (TREE_TYPE (newdecl)); + + if ((TREE_CODE (newdecl) == VAR_DECL + || TREE_CODE (newdecl) == PARM_DECL + || TREE_CODE (newdecl) == RESULT_DECL + || TREE_CODE (newdecl) == FIELD_DECL + || TREE_CODE (newdecl) == TYPE_DECL) + && !(processing_template_decl && uses_template_parms (newdecl))) + layout_decl (newdecl, 0); + + /* Merge the type qualifiers. */ + if (TREE_READONLY (newdecl)) + TREE_READONLY (olddecl) = 1; + if (TREE_THIS_VOLATILE (newdecl)) + TREE_THIS_VOLATILE (olddecl) = 1; + + /* Merge the initialization information. */ + if (DECL_INITIAL (newdecl) == NULL_TREE + && DECL_INITIAL (olddecl) != NULL_TREE) + { + DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); + DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl); + DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl); + if (DECL_LANG_SPECIFIC (newdecl) + && DECL_LANG_SPECIFIC (olddecl)) + DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl); + } + + /* Merge the section attribute. + We want to issue an error if the sections conflict but that must be + done later in decl_attributes since we are called before attributes + are assigned. */ + if (DECL_SECTION_NAME (newdecl) == NULL_TREE) + DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); + + /* Keep the old rtl since we can safely use it, unless it's the + call to abort() used for abstract virtuals. */ + if ((DECL_LANG_SPECIFIC (olddecl) + && !DECL_ABSTRACT_VIRTUAL_P (olddecl)) + || DECL_RTL (olddecl) != DECL_RTL (abort_fndecl)) + DECL_RTL (newdecl) = DECL_RTL (olddecl); + + pop_obstacks (); + } + /* If cannot merge, then use the new type and qualifiers, + and don't preserve the old rtl. */ + else + { + /* Clean out any memory we had of the old declaration. */ + tree oldstatic = value_member (olddecl, static_aggregates); + if (oldstatic) + TREE_VALUE (oldstatic) = error_mark_node; + + TREE_TYPE (olddecl) = TREE_TYPE (newdecl); + TREE_READONLY (olddecl) = TREE_READONLY (newdecl); + TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl); + TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl); + } + + /* Merge the storage class information. */ + DECL_WEAK (newdecl) |= DECL_WEAK (olddecl); + DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl); + TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); + TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl); + if (! DECL_EXTERNAL (olddecl)) + DECL_EXTERNAL (newdecl) = 0; + + if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl)) + { + DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl); + DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl); + DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl); + DECL_TEMPLATE_INSTANTIATED (newdecl) + |= DECL_TEMPLATE_INSTANTIATED (olddecl); + /* Don't really know how much of the language-specific + values we should copy from old to new. */ + DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl); + DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl); + DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); + DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl); + olddecl_friend = DECL_FRIEND_P (olddecl); + + /* Only functions have DECL_BEFRIENDING_CLASSES. */ + if (TREE_CODE (newdecl) == FUNCTION_DECL + || DECL_FUNCTION_TEMPLATE_P (newdecl)) + DECL_BEFRIENDING_CLASSES (newdecl) + = chainon (DECL_BEFRIENDING_CLASSES (newdecl), + DECL_BEFRIENDING_CLASSES (olddecl)); + } + + if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + if (DECL_TEMPLATE_INSTANTIATION (olddecl) + && !DECL_TEMPLATE_INSTANTIATION (newdecl)) + { + /* If newdecl is not a specialization, then it is not a + template-related function at all. And that means that we + shoud have exited above, returning 0. */ + my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl), + 0); + + if (TREE_USED (olddecl)) + /* From [temp.expl.spec]: + + If a template, a member template or the member of a class + template is explicitly specialized then that + specialization shall be declared before the first use of + that specialization that would cause an implicit + instantiation to take place, in every translation unit in + which such a use occurs. */ + cp_error ("explicit specialization of %D after first use", + olddecl); + + SET_DECL_TEMPLATE_SPECIALIZATION (olddecl); + } + DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl); + + /* If either decl says `inline', this fn is inline, unless its + definition was passed already. */ + if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE) + DECL_INLINE (olddecl) = 1; + DECL_INLINE (newdecl) = DECL_INLINE (olddecl); + + if (! types_match) + { + DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl); + DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (newdecl); + DECL_RTL (olddecl) = DECL_RTL (newdecl); + } + if (! types_match || new_defines_function) + { + /* These need to be copied so that the names are available. */ + DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl); + DECL_RESULT (olddecl) = DECL_RESULT (newdecl); + } + if (new_defines_function) + /* If defining a function declared with other language + linkage, use the previously declared language linkage. */ + DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl); + else + { + /* If redeclaring a builtin function, and not a definition, + it stays built in. */ + if (DECL_BUILT_IN (olddecl)) + { + DECL_BUILT_IN (newdecl) = 1; + DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); + /* If we're keeping the built-in definition, keep the rtl, + regardless of declaration matches. */ + DECL_RTL (newdecl) = DECL_RTL (olddecl); + } + else + DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl); + + DECL_RESULT (newdecl) = DECL_RESULT (olddecl); + if ((DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl))) + /* Previously saved insns go together with + the function's previous definition. */ + DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); + /* Don't clear out the arguments if we're redefining a function. */ + if (DECL_ARGUMENTS (olddecl)) + DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); + } + if (DECL_LANG_SPECIFIC (olddecl)) + DECL_MAIN_VARIANT (newdecl) = DECL_MAIN_VARIANT (olddecl); + } + + if (TREE_CODE (newdecl) == NAMESPACE_DECL) + { + NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl); + } + + /* Now preserve various other info from the definition. */ + TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl); + TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl); + DECL_COMMON (newdecl) = DECL_COMMON (olddecl); + DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl); + + if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + int function_size; + struct lang_decl *ol = DECL_LANG_SPECIFIC (olddecl); + struct lang_decl *nl = DECL_LANG_SPECIFIC (newdecl); + + function_size = sizeof (struct tree_decl); + + bcopy ((char *) newdecl + sizeof (struct tree_common), + (char *) olddecl + sizeof (struct tree_common), + function_size - sizeof (struct tree_common)); + + /* Can we safely free the storage used by newdecl? */ + +#define ROUND(x) ((x + obstack_alignment_mask (&permanent_obstack)) \ + & ~ obstack_alignment_mask (&permanent_obstack)) + + if (DECL_TEMPLATE_INSTANTIATION (newdecl)) + { + /* If newdecl is a template instantiation, it is possible that + the following sequence of events has occurred: + + o A friend function was declared in a class template. The + class template was instantiated. + + o The instantiation of the friend declaration was + recorded on the instantiation list, and is newdecl. + + o Later, however, instantiate_class_template called pushdecl + on the newdecl to perform name injection. But, pushdecl in + turn called duplicate_decls when it discovered that another + declaration of a global function with the same name already + existed. + + o Here, in duplicate_decls, we decided to clobber newdecl. + + If we're going to do that, we'd better make sure that + olddecl, and not newdecl, is on the list of + instantiations so that if we try to do the instantiation + again we won't get the clobbered declaration. */ + + tree tmpl = DECL_TI_TEMPLATE (newdecl); + tree decls = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + + for (; decls; decls = TREE_CHAIN (decls)) + if (TREE_VALUE (decls) == newdecl) + TREE_VALUE (decls) = olddecl; + } + + if (((char *)newdecl + ROUND (function_size) == (char *)nl + && ((char *)newdecl + ROUND (function_size) + + ROUND (sizeof (struct lang_decl)) + == obstack_next_free (&permanent_obstack))) + || ((char *)newdecl + ROUND (function_size) + == obstack_next_free (&permanent_obstack))) + { + DECL_MAIN_VARIANT (newdecl) = olddecl; + DECL_LANG_SPECIFIC (olddecl) = ol; + bcopy ((char *)nl, (char *)ol, sizeof (struct lang_decl)); + + obstack_free (&permanent_obstack, newdecl); + } + else if (LANG_DECL_PERMANENT (ol) && ol != nl) + { + if (DECL_MAIN_VARIANT (olddecl) == olddecl) + { + /* Save these lang_decls that would otherwise be lost. */ + extern tree free_lang_decl_chain; + tree free_lang_decl = (tree) ol; + + if (DECL_LANG_SPECIFIC (olddecl) == ol) + abort (); + + TREE_CHAIN (free_lang_decl) = free_lang_decl_chain; + free_lang_decl_chain = free_lang_decl; + } + else + { + /* Storage leak. */; + } + } + } + else + { + bcopy ((char *) newdecl + sizeof (struct tree_common), + (char *) olddecl + sizeof (struct tree_common), + sizeof (struct tree_decl) - sizeof (struct tree_common) + + tree_code_length [(int)TREE_CODE (newdecl)] * sizeof (char *)); + } + + DECL_UID (olddecl) = olddecl_uid; + if (olddecl_friend) + DECL_FRIEND_P (olddecl) = 1; + + /* NEWDECL contains the merged attribute lists. + Update OLDDECL to be the same. */ + DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl); + + return 1; +} + +/* Record a decl-node X as belonging to the current lexical scope. + Check for errors (such as an incompatible declaration for the same + name already seen in the same scope). + + Returns either X or an old decl for the same name. + If an old decl is returned, it may have been smashed + to agree with what X says. */ + +tree +pushdecl (x) + tree x; +{ + register tree t; + register tree name = DECL_ASSEMBLER_NAME (x); + int need_new_binding = 1; + + if (DECL_TEMPLATE_PARM_P (x)) + /* Template parameters have no context; they are not X::T even + when declared within a class or namespace. */ + ; + else + { + if (current_function_decl && x != current_function_decl + /* A local declaration for a function doesn't constitute + nesting. */ + && (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x)) + /* Don't change DECL_CONTEXT of virtual methods. */ + && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x)) + && !DECL_CONTEXT (x)) + DECL_CONTEXT (x) = current_function_decl; + if (!DECL_CONTEXT (x)) + DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace); + } + + /* Type are looked up using the DECL_NAME, as that is what the rest of the + compiler wants to use. */ + if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL + || TREE_CODE (x) == NAMESPACE_DECL) + name = DECL_NAME (x); + + if (name) + { +#if 0 + /* Not needed...see below. */ + char *file; + int line; +#endif + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + name = TREE_OPERAND (name, 0); + + /* Namespace-scoped variables are not found in the current level. */ + if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x)) + t = namespace_binding (name, DECL_CONTEXT (x)); + else + t = lookup_name_current_level (name); + if (t == error_mark_node) + { + /* error_mark_node is 0 for a while during initialization! */ + t = NULL_TREE; + cp_error_at ("`%#D' used prior to declaration", x); + } + + else if (t != NULL_TREE) + { +#if 0 + /* This is turned off until I have time to do it right (bpk). */ + /* With the code below that uses it... */ + file = DECL_SOURCE_FILE (t); + line = DECL_SOURCE_LINE (t); +#endif + if (TREE_CODE (t) == PARM_DECL) + { + if (DECL_CONTEXT (t) == NULL_TREE) + fatal ("parse errors have confused me too much"); + + /* Check for duplicate params. */ + if (duplicate_decls (x, t)) + return t; + } + else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c) + || DECL_FUNCTION_TEMPLATE_P (x)) + && is_overloaded_fn (t)) + /* Don't do anything just yet. */; + else if (t == wchar_decl_node) + { + if (pedantic && ! DECL_IN_SYSTEM_HEADER (x)) + cp_pedwarn ("redeclaration of wchar_t as `%T'", TREE_TYPE (x)); + + /* Throw away the redeclaration. */ + return t; + } + else if (TREE_CODE (t) != TREE_CODE (x)) + { + if (duplicate_decls (x, t)) + return t; + } + else if (duplicate_decls (x, t)) + { +#if 0 + /* This is turned off until I have time to do it right (bpk). */ + + /* Also warn if they did a prototype with `static' on it, but + then later left the `static' off. */ + if (! TREE_PUBLIC (name) && TREE_PUBLIC (x)) + { + if (DECL_LANG_SPECIFIC (t) && DECL_FRIEND_P (t)) + return t; + + if (extra_warnings) + { + cp_warning ("`static' missing from declaration of `%D'", + t); + warning_with_file_and_line (file, line, + "previous declaration of `%s'", + decl_as_string (t, 0)); + } + + /* Now fix things so it'll do what they expect. */ + if (current_function_decl) + TREE_PUBLIC (current_function_decl) = 0; + } + /* Due to interference in memory reclamation (X may be + obstack-deallocated at this point), we must guard against + one really special case. [jason: This should be handled + by start_function] */ + if (current_function_decl == x) + current_function_decl = t; +#endif + if (TREE_CODE (t) == TYPE_DECL) + SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t)); + else if (TREE_CODE (t) == FUNCTION_DECL) + check_default_args (t); + + return t; + } + else if (DECL_MAIN_P (x)) + { + /* A redeclaration of main, but not a duplicate of the + previous one. + + [basic.start.main] + + This function shall not be overloaded. */ + cp_error_at ("invalid redeclaration of `%D'", t); + cp_error ("as `%D'", x); + /* We don't try to push this declaration since that + causes a crash. */ + return x; + } + } + + check_template_shadow (x); + + /* If this is a function conjured up by the backend, massage it + so it looks friendly. */ + if (TREE_CODE (x) == FUNCTION_DECL + && ! DECL_LANG_SPECIFIC (x)) + { + retrofit_lang_decl (x); + DECL_LANGUAGE (x) = lang_c; + } + + if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x)) + { + t = push_overloaded_decl (x, PUSH_LOCAL); + if (t != x || DECL_LANGUAGE (x) == lang_c) + return t; + if (!namespace_bindings_p ()) + /* We do not need to create a binding for this name; + push_overloaded_decl will have already done so if + necessary. */ + need_new_binding = 0; + } + else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x)) + return push_overloaded_decl (x, PUSH_GLOBAL); + + /* If declaring a type as a typedef, copy the type (unless we're + at line 0), and install this TYPE_DECL as the new type's typedef + name. See the extensive comment in ../c-decl.c (pushdecl). */ + if (TREE_CODE (x) == TYPE_DECL) + { + tree type = TREE_TYPE (x); + if (DECL_SOURCE_LINE (x) == 0) + { + if (TYPE_NAME (type) == 0) + TYPE_NAME (type) = x; + } + else if (type != error_mark_node && TYPE_NAME (type) != x + /* We don't want to copy the type when all we're + doing is making a TYPE_DECL for the purposes of + inlining. */ + && (!TYPE_NAME (type) + || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))) + { + push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type)); + + DECL_ORIGINAL_TYPE (x) = type; + type = build_type_copy (type); + TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x)); + TYPE_NAME (type) = x; + TREE_TYPE (x) = type; + + pop_obstacks (); + } + + if (type != error_mark_node + && TYPE_NAME (type) + && TYPE_IDENTIFIER (type)) + set_identifier_type_value_with_scope (DECL_NAME (x), type, + current_binding_level); + + } + + /* Multiple external decls of the same identifier ought to match. + + We get warnings about inline functions where they are defined. + We get warnings about other functions from push_overloaded_decl. + + Avoid duplicate warnings where they are used. */ + if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL) + { + tree decl; + + if (IDENTIFIER_NAMESPACE_VALUE (name) != NULL_TREE + && (DECL_EXTERNAL (IDENTIFIER_NAMESPACE_VALUE (name)) + || TREE_PUBLIC (IDENTIFIER_NAMESPACE_VALUE (name)))) + decl = IDENTIFIER_NAMESPACE_VALUE (name); + else + decl = NULL_TREE; + + if (decl + /* If different sort of thing, we already gave an error. */ + && TREE_CODE (decl) == TREE_CODE (x) + && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl))) + { + cp_pedwarn ("type mismatch with previous external decl", x); + cp_pedwarn_at ("previous external decl of `%#D'", decl); + } + } + + /* This name is new in its binding level. + Install the new declaration and return it. */ + if (namespace_bindings_p ()) + { + /* Install a global value. */ + + /* If the first global decl has external linkage, + warn if we later see static one. */ + if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x)) + TREE_PUBLIC (name) = 1; + + if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x) + && t != NULL_TREE)) + { + if (TREE_CODE (x) == FUNCTION_DECL) + my_friendly_assert + ((IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE) + || (IDENTIFIER_GLOBAL_VALUE (name) == x), 378); + SET_IDENTIFIER_NAMESPACE_VALUE (name, x); + } + + /* Don't forget if the function was used via an implicit decl. */ + if (IDENTIFIER_IMPLICIT_DECL (name) + && TREE_USED (IDENTIFIER_IMPLICIT_DECL (name))) + TREE_USED (x) = 1; + + /* Don't forget if its address was taken in that way. */ + if (IDENTIFIER_IMPLICIT_DECL (name) + && TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name))) + TREE_ADDRESSABLE (x) = 1; + + /* Warn about mismatches against previous implicit decl. */ + if (IDENTIFIER_IMPLICIT_DECL (name) != NULL_TREE + /* If this real decl matches the implicit, don't complain. */ + && ! (TREE_CODE (x) == FUNCTION_DECL + && TREE_TYPE (TREE_TYPE (x)) == integer_type_node)) + cp_warning + ("`%D' was previously implicitly declared to return `int'", x); + + /* If new decl is `static' and an `extern' was seen previously, + warn about it. */ + if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t)) + warn_extern_redeclared_static (x, t); + } + else + { + /* Here to install a non-global value. */ + tree oldlocal = IDENTIFIER_VALUE (name); + tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name); + + if (need_new_binding) + { + push_local_binding (name, x, 0); + /* Because push_local_binding will hook X on to the + current_binding_level's name list, we don't want to + do that again below. */ + need_new_binding = 0; + } + + /* If this is a TYPE_DECL, push it into the type value slot. */ + if (TREE_CODE (x) == TYPE_DECL) + set_identifier_type_value_with_scope (name, TREE_TYPE (x), + current_binding_level); + + /* Clear out any TYPE_DECL shadowed by a namespace so that + we won't think this is a type. The C struct hack doesn't + go through namespaces. */ + if (TREE_CODE (x) == NAMESPACE_DECL) + set_identifier_type_value_with_scope (name, NULL_TREE, + current_binding_level); + + /* If this is an extern function declaration, see if we + have a global definition or declaration for the function. */ + if (oldlocal == NULL_TREE + && DECL_EXTERNAL (x) + && oldglobal != NULL_TREE + && TREE_CODE (x) == FUNCTION_DECL + && TREE_CODE (oldglobal) == FUNCTION_DECL) + { + /* We have one. Their types must agree. */ + if (decls_match (x, oldglobal)) + /* OK */; + else + { + cp_warning ("extern declaration of `%#D' doesn't match", x); + cp_warning_at ("global declaration `%#D'", oldglobal); + } + } + /* If we have a local external declaration, + and no file-scope declaration has yet been seen, + then if we later have a file-scope decl it must not be static. */ + if (oldlocal == NULL_TREE + && oldglobal == NULL_TREE + && DECL_EXTERNAL (x) + && TREE_PUBLIC (x)) + TREE_PUBLIC (name) = 1; + + if (DECL_FROM_INLINE (x)) + /* Inline decls shadow nothing. */; + + /* Warn if shadowing an argument at the top level of the body. */ + else if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x) + && TREE_CODE (oldlocal) == PARM_DECL + /* Don't complain if it's from an enclosing function. */ + && DECL_CONTEXT (oldlocal) == current_function_decl + && TREE_CODE (x) != PARM_DECL) + { + /* Go to where the parms should be and see if we + find them there. */ + struct binding_level *b = current_binding_level->level_chain; + + if (cleanup_label) + b = b->level_chain; + + /* ARM $8.3 */ + if (b->parm_flag == 1) + cp_error ("declaration of `%#D' shadows a parameter", name); + } + else if (warn_shadow && oldlocal != NULL_TREE + && current_binding_level->is_for_scope + && !DECL_DEAD_FOR_LOCAL (oldlocal)) + { + warning ("variable `%s' shadows local", + IDENTIFIER_POINTER (name)); + cp_warning_at (" this is the shadowed declaration", oldlocal); + } + /* Maybe warn if shadowing something else. */ + else if (warn_shadow && !DECL_EXTERNAL (x) + /* No shadow warnings for internally generated vars. */ + && ! DECL_ARTIFICIAL (x) + /* No shadow warnings for vars made for inlining. */ + && ! DECL_FROM_INLINE (x)) + { + const char *warnstring = NULL; + + if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL) + warnstring = "declaration of `%s' shadows a parameter"; + else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE + && current_class_ptr + && !TREE_STATIC (name)) + warnstring = "declaration of `%s' shadows a member of `this'"; + else if (oldlocal != NULL_TREE) + warnstring = "declaration of `%s' shadows previous local"; + else if (oldglobal != NULL_TREE) + /* XXX shadow warnings in outer-more namespaces */ + warnstring = "declaration of `%s' shadows global declaration"; + + if (warnstring) + warning (warnstring, IDENTIFIER_POINTER (name)); + } + } + + if (TREE_CODE (x) == FUNCTION_DECL) + check_default_args (x); + + /* Keep count of variables in this level with incomplete type. */ + if (TREE_CODE (x) == VAR_DECL + && TREE_TYPE (x) != error_mark_node + && ((TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE + && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE)) + /* RTTI TD entries are created while defining the type_info. */ + || (TYPE_LANG_SPECIFIC (TREE_TYPE (x)) + && TYPE_BEING_DEFINED (TREE_TYPE (x))))) + current_binding_level->incomplete + = tree_cons (NULL_TREE, x, current_binding_level->incomplete); + } + + if (need_new_binding) + { + /* Put decls on list in reverse order. + We will reverse them later if necessary. */ + TREE_CHAIN (x) = current_binding_level->names; + current_binding_level->names = x; + if (current_binding_level == global_binding_level + && !TREE_PERMANENT (x)) + my_friendly_abort (124); + } + + return x; +} + +/* Same as pushdecl, but define X in binding-level LEVEL. We rely on the + caller to set DECL_CONTEXT properly. */ + +static tree +pushdecl_with_scope (x, level) + tree x; + struct binding_level *level; +{ + register struct binding_level *b; + tree function_decl = current_function_decl; + + current_function_decl = NULL_TREE; + if (level->parm_flag == 2) + { + b = class_binding_level; + class_binding_level = level; + pushdecl_class_level (x); + class_binding_level = b; + } + else + { + b = current_binding_level; + current_binding_level = level; + x = pushdecl (x); + current_binding_level = b; + } + current_function_decl = function_decl; + return x; +} + +/* Like pushdecl, only it places X in the current namespace, + if appropriate. */ + +tree +pushdecl_namespace_level (x) + tree x; +{ + register struct binding_level *b = current_binding_level; + register tree t; + + t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace)); + + /* Now, the type_shadowed stack may screw us. Munge it so it does + what we want. */ + if (TREE_CODE (x) == TYPE_DECL) + { + tree name = DECL_NAME (x); + tree newval; + tree *ptr = (tree *)0; + for (; b != global_binding_level; b = b->level_chain) + { + tree shadowed = b->type_shadowed; + for (; shadowed; shadowed = TREE_CHAIN (shadowed)) + if (TREE_PURPOSE (shadowed) == name) + { + ptr = &TREE_VALUE (shadowed); + /* Can't break out of the loop here because sometimes + a binding level will have duplicate bindings for + PT names. It's gross, but I haven't time to fix it. */ + } + } + newval = TREE_TYPE (x); + if (ptr == (tree *)0) + { + /* @@ This shouldn't be needed. My test case "zstring.cc" trips + up here if this is changed to an assertion. --KR */ + SET_IDENTIFIER_TYPE_VALUE (name, newval); + } + else + { + *ptr = newval; + } + } + return t; +} + +/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, + if appropriate. */ + +tree +pushdecl_top_level (x) + tree x; +{ + tree cur_namespace = current_namespace; + current_namespace = global_namespace; + x = pushdecl_namespace_level (x); + current_namespace = cur_namespace; + return x; +} + +/* Make the declaration of X appear in CLASS scope. */ + +void +pushdecl_class_level (x) + tree x; +{ + /* Don't use DECL_ASSEMBLER_NAME here! Everything that looks in class + scope looks for the pre-mangled name. */ + register tree name; + + if (TREE_CODE (x) == OVERLOAD) + x = OVL_CURRENT (x); + name = DECL_NAME (x); + + if (name) + { + push_class_level_binding (name, x); + if (TREE_CODE (x) == TYPE_DECL) + set_identifier_type_value (name, TREE_TYPE (x)); + } + else if (ANON_UNION_TYPE_P (TREE_TYPE (x))) + { + tree f; + + for (f = TYPE_FIELDS (TREE_TYPE (x)); + f; + f = TREE_CHAIN (f)) + pushdecl_class_level (f); + } +} + +#if 0 +/* This function is used to push the mangled decls for nested types into + the appropriate scope. Previously pushdecl_top_level was used, but that + is incorrect for members of local classes. */ + +void +pushdecl_nonclass_level (x) + tree x; +{ + struct binding_level *b = current_binding_level; + + my_friendly_assert (b->parm_flag != 2, 180); + +#if 0 + /* Get out of template binding levels */ + while (b->pseudo_global) + b = b->level_chain; +#endif + + pushdecl_with_scope (x, b); +} +#endif + +/* Make the declaration(s) of X appear in CLASS scope + under the name NAME. */ + +void +push_class_level_binding (name, x) + tree name; + tree x; +{ + tree binding; + /* The class_binding_level will be NULL if x is a template + parameter name in a member template. */ + if (!class_binding_level) + return; + + /* Make sure that this new member does not have the same name + as a template parameter. */ + if (TYPE_BEING_DEFINED (current_class_type)) + check_template_shadow (x); + + /* If this declaration shadows a declaration from an enclosing + class, then we will need to restore IDENTIFIER_CLASS_VALUE when + we leave this class. Record the shadowed declaration here. */ + binding = IDENTIFIER_BINDING (name); + if (binding + && ((TREE_CODE (x) == OVERLOAD + && BINDING_VALUE (binding) + && is_overloaded_fn (BINDING_VALUE (binding))) + || INHERITED_VALUE_BINDING_P (binding))) + { + tree shadow; + tree old_decl; + + /* If the old binding was from a base class, and was for a tag + name, slide it over to make room for the new binding. The + old binding is still visible if explicitly qualified with a + class-key. */ + if (INHERITED_VALUE_BINDING_P (binding) + && BINDING_VALUE (binding) + && TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL + && DECL_ARTIFICIAL (BINDING_VALUE (binding)) + && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))) + { + old_decl = BINDING_TYPE (binding); + BINDING_TYPE (binding) = BINDING_VALUE (binding); + BINDING_VALUE (binding) = NULL_TREE; + INHERITED_VALUE_BINDING_P (binding) = 0; + } + else + old_decl = BINDING_VALUE (binding); + + /* There was already a binding for X containing fewer + functions than are named in X. Find the previous + declaration of X on the class-shadowed list, and update it. */ + for (shadow = class_binding_level->class_shadowed; + shadow; + shadow = TREE_CHAIN (shadow)) + if (TREE_PURPOSE (shadow) == name + && TREE_TYPE (shadow) == old_decl) + { + BINDING_VALUE (binding) = x; + INHERITED_VALUE_BINDING_P (binding) = 0; + TREE_TYPE (shadow) = x; + return; + } + } + + /* If we didn't replace an existing binding, put the binding on the + stack of bindings for the identifier, and update + IDENTIFIER_CLASS_VALUE. */ + if (push_class_binding (name, x)) + { + push_cache_obstack (); + class_binding_level->class_shadowed + = tree_cons (name, IDENTIFIER_CLASS_VALUE (name), + class_binding_level->class_shadowed); + pop_obstacks (); + /* Record the value we are binding NAME to so that we can know + what to pop later. */ + TREE_TYPE (class_binding_level->class_shadowed) = x; + } +} + +/* Insert another USING_DECL into the current binding level, + returning this declaration. If this is a redeclaration, + do nothing and return NULL_TREE. */ + +tree +push_using_decl (scope, name) + tree scope; + tree name; +{ + tree decl; + + my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383); + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384); + for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl)) + if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name) + break; + if (decl) + return NULL_TREE; + decl = build_lang_decl (USING_DECL, name, void_type_node); + DECL_INITIAL (decl) = scope; + TREE_CHAIN (decl) = current_binding_level->usings; + current_binding_level->usings = decl; + return decl; +} + +/* Add namespace to using_directives. Return NULL_TREE if nothing was + changed (i.e. there was already a directive), or the fresh + TREE_LIST otherwise. */ + +tree +push_using_directive (used) + tree used; +{ + tree ud = current_binding_level->using_directives; + tree iter, ancestor; + + /* Check if we already have this. */ + if (purpose_member (used, ud) != NULL_TREE) + return NULL_TREE; + + /* Recursively add all namespaces used. */ + for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter)) + push_using_directive (TREE_PURPOSE (iter)); + + ancestor = namespace_ancestor (current_decl_namespace (), used); + ud = current_binding_level->using_directives; + ud = perm_tree_cons (used, ancestor, ud); + current_binding_level->using_directives = ud; + return ud; +} + +/* DECL is a FUNCTION_DECL for a non-member function, which may have + other definitions already in place. We get around this by making + the value of the identifier point to a list of all the things that + want to be referenced by that name. It is then up to the users of + that name to decide what to do with that list. + + DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT + slot. It is dealt with the same way. + + FLAGS is a bitwise-or of the following values: + PUSH_LOCAL: Bind DECL in the current scope, rather than at + namespace scope. + PUSH_USING: DECL is being pushed as the result of a using + declaration. + + The value returned may be a previous declaration if we guessed wrong + about what language DECL should belong to (C or C++). Otherwise, + it's always DECL (and never something that's not a _DECL). */ + +tree +push_overloaded_decl (decl, flags) + tree decl; + int flags; +{ + tree name = DECL_NAME (decl); + tree old; + tree new_binding; + int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL)); + + if (doing_global) + { + old = namespace_binding (name, DECL_CONTEXT (decl)); + if (old && TREE_CODE (old) == FUNCTION_DECL + && DECL_ARTIFICIAL (old) + && (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old))) + { + if (duplicate_decls (decl, old)) + return old; + old = NULL_TREE; + } + } + else + old = lookup_name_current_level (name); + + if (old) + { + if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old)) + { + tree t = TREE_TYPE (old); + if (IS_AGGR_TYPE (t) && warn_shadow + && (! DECL_IN_SYSTEM_HEADER (decl) + || ! DECL_IN_SYSTEM_HEADER (old))) + cp_warning ("`%#D' hides constructor for `%#T'", decl, t); + old = NULL_TREE; + } + else if (is_overloaded_fn (old)) + { + tree tmp; + + for (tmp = old; tmp; tmp = OVL_NEXT (tmp)) + { + tree fn = OVL_CURRENT (tmp); + + if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp) + && !(flags & PUSH_USING) + && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)), + TYPE_ARG_TYPES (TREE_TYPE (decl)))) + cp_error ("`%#D' conflicts with previous using declaration `%#D'", + decl, fn); + + if (duplicate_decls (decl, fn)) + return fn; + } + } + else + { + cp_error_at ("previous non-function declaration `%#D'", old); + cp_error ("conflicts with function declaration `%#D'", decl); + return decl; + } + } + + if (old || TREE_CODE (decl) == TEMPLATE_DECL) + { + if (old && TREE_CODE (old) != OVERLOAD) + new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE)); + else + new_binding = ovl_cons (decl, old); + if (flags & PUSH_USING) + OVL_USED (new_binding) = 1; + } + else + /* NAME is not ambiguous. */ + new_binding = decl; + + if (doing_global) + set_namespace_binding (name, current_namespace, new_binding); + else + { + /* We only create an OVERLOAD if there was a previous binding at + this level, or if decl is a template. In the former case, we + need to remove the old binding and replace it with the new + binding. We must also run through the NAMES on the binding + level where the name was bound to update the chain. */ + + if (TREE_CODE (new_binding) == OVERLOAD && old) + { + tree *d; + + for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names; + *d; + d = &TREE_CHAIN (*d)) + if (*d == old + || (TREE_CODE (*d) == TREE_LIST + && TREE_VALUE (*d) == old)) + { + if (TREE_CODE (*d) == TREE_LIST) + /* Just replace the old binding with the new. */ + TREE_VALUE (*d) = new_binding; + else + /* Build a TREE_LIST to wrap the OVERLOAD. */ + *d = build_tree_list (NULL_TREE, new_binding); + + /* And update the CPLUS_BINDING node. */ + BINDING_VALUE (IDENTIFIER_BINDING (name)) + = new_binding; + return decl; + } + + /* We should always find a previous binding in this case. */ + my_friendly_abort (0); + } + + /* Install the new binding. */ + push_local_binding (name, new_binding, flags); + } + + return decl; +} + +/* Generate an implicit declaration for identifier FUNCTIONID + as a function of type int (). Print a warning if appropriate. */ + +tree +implicitly_declare (functionid) + tree functionid; +{ + register tree decl; + int temp = allocation_temporary_p (); + + push_obstacks_nochange (); + + /* Save the decl permanently so we can warn if definition follows. + In ANSI C, warn_implicit is usually false, so the saves little space. + But in C++, it's usually true, hence the extra code. */ + if (temp && (! warn_implicit || toplevel_bindings_p ())) + end_temporary_allocation (); + + /* We used to reuse an old implicit decl here, + but this loses with inline functions because it can clobber + the saved decl chains. */ + decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type); + + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + + /* ANSI standard says implicit declarations are in the innermost block. + So we record the decl in the standard fashion. */ + pushdecl (decl); + rest_of_decl_compilation (decl, NULL_PTR, 0, 0); + + if (warn_implicit + /* Only one warning per identifier. */ + && IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE) + { + cp_pedwarn ("implicit declaration of function `%#D'", decl); + } + + SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl); + + pop_obstacks (); + + return decl; +} + +/* Return zero if the declaration NEWDECL is valid + when the declaration OLDDECL (assumed to be for the same name) + has already been seen. + Otherwise return an error message format string with a %s + where the identifier should go. */ + +static const char * +redeclaration_error_message (newdecl, olddecl) + tree newdecl, olddecl; +{ + if (TREE_CODE (newdecl) == TYPE_DECL) + { + /* Because C++ can put things into name space for free, + constructs like "typedef struct foo { ... } foo" + would look like an erroneous redeclaration. */ + if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl))) + return 0; + else + return "redefinition of `%#D'"; + } + else if (TREE_CODE (newdecl) == FUNCTION_DECL) + { + /* If this is a pure function, its olddecl will actually be + the original initialization to `0' (which we force to call + abort()). Don't complain about redefinition in this case. */ + if (DECL_LANG_SPECIFIC (olddecl) && DECL_ABSTRACT_VIRTUAL_P (olddecl)) + return 0; + + /* If both functions come from different namespaces, this is not + a redeclaration - this is a conflict with a used function. */ + if (DECL_NAMESPACE_SCOPE_P (olddecl) + && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)) + return "`%D' conflicts with used function"; + + /* We'll complain about linkage mismatches in + warn_extern_redeclared_static. */ + + /* Defining the same name twice is no good. */ + if (DECL_INITIAL (olddecl) != NULL_TREE + && DECL_INITIAL (newdecl) != NULL_TREE) + { + if (DECL_NAME (olddecl) == NULL_TREE) + return "`%#D' not declared in class"; + else + return "redefinition of `%#D'"; + } + return 0; + } + else if (TREE_CODE (newdecl) == TEMPLATE_DECL) + { + if ((TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL + && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) + && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl))) + || (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL + && TYPE_SIZE (TREE_TYPE (newdecl)) + && TYPE_SIZE (TREE_TYPE (olddecl)))) + return "redefinition of `%#D'"; + return 0; + } + else if (toplevel_bindings_p ()) + { + /* Objects declared at top level: */ + /* If at least one is a reference, it's ok. */ + if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl)) + return 0; + /* Reject two definitions. */ + return "redefinition of `%#D'"; + } + else + { + /* Objects declared with block scope: */ + /* Reject two definitions, and reject a definition + together with an external reference. */ + if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))) + return "redeclaration of `%#D'"; + return 0; + } +} + +/* Get the LABEL_DECL corresponding to identifier ID as a label. + Create one if none exists so far for the current function. + This function is called for both label definitions and label references. */ + +tree +lookup_label (id) + tree id; +{ + register tree decl = IDENTIFIER_LABEL_VALUE (id); + + if (current_function_decl == NULL_TREE) + { + error ("label `%s' referenced outside of any function", + IDENTIFIER_POINTER (id)); + return NULL_TREE; + } + + if ((decl == NULL_TREE + || DECL_SOURCE_LINE (decl) == 0) + && (named_label_uses == NULL + || named_label_uses->names_in_scope != current_binding_level->names + || named_label_uses->label_decl != decl)) + { + struct named_label_list *new_ent; + new_ent + = (struct named_label_list*)oballoc (sizeof (struct named_label_list)); + new_ent->label_decl = decl; + new_ent->names_in_scope = current_binding_level->names; + new_ent->binding_level = current_binding_level; + new_ent->lineno_o_goto = lineno; + new_ent->filename_o_goto = input_filename; + new_ent->next = named_label_uses; + named_label_uses = new_ent; + } + + /* Use a label already defined or ref'd with this name. */ + if (decl != NULL_TREE) + { + /* But not if it is inherited and wasn't declared to be inheritable. */ + if (DECL_CONTEXT (decl) != current_function_decl + && ! C_DECLARED_LABEL_FLAG (decl)) + return shadow_label (id); + return decl; + } + + decl = build_decl (LABEL_DECL, id, void_type_node); + + /* Make sure every label has an rtx. */ + label_rtx (decl); + + /* A label not explicitly declared must be local to where it's ref'd. */ + DECL_CONTEXT (decl) = current_function_decl; + + DECL_MODE (decl) = VOIDmode; + + /* Say where one reference is to the label, + for the sake of the error if it is not defined. */ + DECL_SOURCE_LINE (decl) = lineno; + DECL_SOURCE_FILE (decl) = input_filename; + + SET_IDENTIFIER_LABEL_VALUE (id, decl); + + named_labels = tree_cons (NULL_TREE, decl, named_labels); + named_label_uses->label_decl = decl; + + return decl; +} + +/* Make a label named NAME in the current function, + shadowing silently any that may be inherited from containing functions + or containing scopes. + + Note that valid use, if the label being shadowed + comes from another scope in the same function, + requires calling declare_nonlocal_label right away. */ + +tree +shadow_label (name) + tree name; +{ + register tree decl = IDENTIFIER_LABEL_VALUE (name); + + if (decl != NULL_TREE) + { + shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels); + SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE); + } + + return lookup_label (name); +} + +/* Define a label, specifying the location in the source file. + Return the LABEL_DECL node for the label, if the definition is valid. + Otherwise return 0. */ + +tree +define_label (filename, line, name) + char *filename; + int line; + tree name; +{ + tree decl; + + if (minimal_parse_mode) + { + push_obstacks (&permanent_obstack, &permanent_obstack); + decl = build_decl (LABEL_DECL, name, void_type_node); + pop_obstacks (); + DECL_SOURCE_LINE (decl) = line; + DECL_SOURCE_FILE (decl) = filename; + add_tree (decl); + return decl; + } + + decl = lookup_label (name); + + /* After labels, make any new cleanups go into their + own new (temporary) binding contour. */ + current_binding_level->more_cleanups_ok = 0; + + /* If label with this name is known from an outer context, shadow it. */ + if (decl != NULL_TREE && DECL_CONTEXT (decl) != current_function_decl) + { + shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels); + SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE); + decl = lookup_label (name); + } + + if (name == get_identifier ("wchar_t")) + cp_pedwarn ("label named wchar_t"); + + if (DECL_INITIAL (decl) != NULL_TREE) + { + cp_error ("duplicate label `%D'", decl); + return 0; + } + else + { + struct named_label_list *uses, *prev; + int identified = 0; + + /* Mark label as having been defined. */ + DECL_INITIAL (decl) = error_mark_node; + /* Say where in the source. */ + DECL_SOURCE_FILE (decl) = filename; + DECL_SOURCE_LINE (decl) = line; + + prev = NULL; + uses = named_label_uses; + while (uses != NULL) + if (uses->label_decl == decl) + { + struct binding_level *b = current_binding_level; + while (b) + { + tree new_decls = b->names; + tree old_decls = (b == uses->binding_level) + ? uses->names_in_scope : NULL_TREE; + while (new_decls != old_decls) + { + if (TREE_CODE (new_decls) == VAR_DECL + /* Don't complain about crossing initialization + of internal entities. They can't be accessed, + and they should be cleaned up + by the time we get to the label. */ + && ! DECL_ARTIFICIAL (new_decls) + && !(DECL_INITIAL (new_decls) == NULL_TREE + && pod_type_p (TREE_TYPE (new_decls)))) + { + /* This is really only important if we're crossing + an initialization. The POD stuff is just + pedantry; why should it matter if the class + contains a field of pointer to member type? */ + int problem = (DECL_INITIAL (new_decls) + || (TYPE_NEEDS_CONSTRUCTING + (TREE_TYPE (new_decls)))); + + if (! identified) + { + if (problem) + { + cp_error ("jump to label `%D'", decl); + error_with_file_and_line + (uses->filename_o_goto, + uses->lineno_o_goto, " from here"); + } + else + { + cp_pedwarn ("jump to label `%D'", decl); + pedwarn_with_file_and_line + (uses->filename_o_goto, + uses->lineno_o_goto, " from here"); + } + identified = 1; + } + + if (problem) + cp_error_at (" crosses initialization of `%#D'", + new_decls); + else + cp_pedwarn_at (" enters scope of non-POD `%#D'", + new_decls); + } + new_decls = TREE_CHAIN (new_decls); + } + if (b == uses->binding_level) + break; + b = b->level_chain; + } + + if (prev != NULL) + prev->next = uses->next; + else + named_label_uses = uses->next; + + uses = uses->next; + } + else + { + prev = uses; + uses = uses->next; + } + current_function_return_value = NULL_TREE; + return decl; + } +} + +struct cp_switch +{ + struct binding_level *level; + struct cp_switch *next; +}; + +static struct cp_switch *switch_stack; + +void +push_switch () +{ + struct cp_switch *p + = (struct cp_switch *) oballoc (sizeof (struct cp_switch)); + p->level = current_binding_level; + p->next = switch_stack; + switch_stack = p; +} + +void +pop_switch () +{ + switch_stack = switch_stack->next; +} + +/* Same, but for CASE labels. If DECL is NULL_TREE, it's the default. */ +/* XXX Note decl is never actually used. (bpk) */ + +void +define_case_label () +{ + tree cleanup = last_cleanup_this_contour (); + struct binding_level *b = current_binding_level; + int identified = 0; + + if (cleanup) + { + static int explained = 0; + cp_warning_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup)); + warning ("where case label appears here"); + if (!explained) + { + warning ("(enclose actions of previous case statements requiring"); + warning ("destructors in their own binding contours.)"); + explained = 1; + } + } + + for (; b && b != switch_stack->level; b = b->level_chain) + { + tree new_decls = b->names; + for (; new_decls; new_decls = TREE_CHAIN (new_decls)) + { + if (TREE_CODE (new_decls) == VAR_DECL + /* Don't complain about crossing initialization + of internal entities. They can't be accessed, + and they should be cleaned up + by the time we get to the label. */ + && ! DECL_ARTIFICIAL (new_decls) + && ((DECL_INITIAL (new_decls) != NULL_TREE + && DECL_INITIAL (new_decls) != error_mark_node) + || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls)))) + { + if (! identified) + error ("jump to case label"); + identified = 1; + cp_error_at (" crosses initialization of `%#D'", + new_decls); + } + } + } + + /* After labels, make any new cleanups go into their + own new (temporary) binding contour. */ + + current_binding_level->more_cleanups_ok = 0; + current_function_return_value = NULL_TREE; +} + +/* Return the list of declarations of the current level. + Note that this list is in reverse order unless/until + you nreverse it; and when you do nreverse it, you must + store the result back using `storedecls' or you will lose. */ + +tree +getdecls () +{ + return current_binding_level->names; +} + +/* Return the list of type-tags (for structs, etc) of the current level. */ + +tree +gettags () +{ + return current_binding_level->tags; +} + +/* Store the list of declarations of the current level. + This is done for the parameter declarations of a function being defined, + after they are modified in the light of any missing parameters. */ + +static void +storedecls (decls) + tree decls; +{ + current_binding_level->names = decls; +} + +/* Similarly, store the list of tags of the current level. */ + +void +storetags (tags) + tree tags; +{ + current_binding_level->tags = tags; +} + +/* Given NAME, an IDENTIFIER_NODE, + return the structure (or union or enum) definition for that name. + Searches binding levels from BINDING_LEVEL up to the global level. + If THISLEVEL_ONLY is nonzero, searches only the specified context + (but skips any tag-transparent contexts to find one that is + meaningful for tags). + FORM says which kind of type the caller wants; + it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE. + If the wrong kind of type is found, and it's not a template, an error is + reported. */ + +static tree +lookup_tag (form, name, binding_level, thislevel_only) + enum tree_code form; + tree name; + struct binding_level *binding_level; + int thislevel_only; +{ + register struct binding_level *level; + /* Non-zero if, we should look past a pseudo-global level, even if + THISLEVEL_ONLY. */ + int allow_pseudo_global = 1; + + for (level = binding_level; level; level = level->level_chain) + { + register tree tail; + if (ANON_AGGRNAME_P (name)) + for (tail = level->tags; tail; tail = TREE_CHAIN (tail)) + { + /* There's no need for error checking here, because + anon names are unique throughout the compilation. */ + if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name) + return TREE_VALUE (tail); + } + else if (level->namespace_p) + /* Do namespace lookup. */ + for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail)) + { + tree old = binding_for_name (name, tail); + + /* If we just skipped past a pseudo global level, even + though THISLEVEL_ONLY, and we find a template class + declaration, then we use the _TYPE node for the + template. See the example below. */ + if (thislevel_only && !allow_pseudo_global + && old && BINDING_VALUE (old) + && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old))) + old = TREE_TYPE (BINDING_VALUE (old)); + else + old = BINDING_TYPE (old); + + /* If it has an original type, it is a typedef, and we + should not return it. */ + if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old))) + old = NULL_TREE; + if (old && TREE_CODE (old) != form + && !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL)) + { + cp_error ("`%#D' redeclared as %C", old, form); + return NULL_TREE; + } + if (old) + return old; + if (thislevel_only || tail == global_namespace) + return NULL_TREE; + } + else + for (tail = level->tags; tail; tail = TREE_CHAIN (tail)) + { + if (TREE_PURPOSE (tail) == name) + { + enum tree_code code = TREE_CODE (TREE_VALUE (tail)); + /* Should tighten this up; it'll probably permit + UNION_TYPE and a struct template, for example. */ + if (code != form + && !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL)) + { + /* Definition isn't the kind we were looking for. */ + cp_error ("`%#D' redeclared as %C", TREE_VALUE (tail), + form); + return NULL_TREE; + } + return TREE_VALUE (tail); + } + } + if (thislevel_only && ! level->tag_transparent) + { + if (level->pseudo_global && allow_pseudo_global) + { + /* We must deal with cases like this: + + template struct S; + template struct S {}; + + When looking up `S', for the second declaration, we + would like to find the first declaration. But, we + are in the pseudo-global level created for the + template parameters, rather than the (surrounding) + namespace level. Thus, we keep going one more level, + even though THISLEVEL_ONLY is non-zero. */ + allow_pseudo_global = 0; + continue; + } + else + return NULL_TREE; + } + if (current_class_type && level->level_chain->namespace_p) + { + /* Try looking in this class's tags before heading into + global binding level. */ + tree context = current_class_type; + while (context) + { + switch (TREE_CODE_CLASS (TREE_CODE (context))) + { + tree these_tags; + case 't': + these_tags = CLASSTYPE_TAGS (context); + if (ANON_AGGRNAME_P (name)) + while (these_tags) + { + if (TYPE_IDENTIFIER (TREE_VALUE (these_tags)) + == name) + return TREE_VALUE (tail); + these_tags = TREE_CHAIN (these_tags); + } + else + while (these_tags) + { + if (TREE_PURPOSE (these_tags) == name) + { + if (TREE_CODE (TREE_VALUE (these_tags)) != form) + { + cp_error ("`%#D' redeclared as %C in class scope", + TREE_VALUE (tail), form); + return NULL_TREE; + } + return TREE_VALUE (tail); + } + these_tags = TREE_CHAIN (these_tags); + } + /* If this type is not yet complete, then don't + look at its context. */ + if (TYPE_SIZE (context) == NULL_TREE) + goto no_context; + /* Go to next enclosing type, if any. */ + context = DECL_CONTEXT (TYPE_MAIN_DECL (context)); + break; + case 'd': + context = DECL_CONTEXT (context); + break; + default: + my_friendly_abort (10); + } + continue; + no_context: + break; + } + } + } + return NULL_TREE; +} + +#if 0 +void +set_current_level_tags_transparency (tags_transparent) + int tags_transparent; +{ + current_binding_level->tag_transparent = tags_transparent; +} +#endif + +/* Given a type, find the tag that was defined for it and return the tag name. + Otherwise return 0. However, the value can never be 0 + in the cases in which this is used. + + C++: If NAME is non-zero, this is the new name to install. This is + done when replacing anonymous tags with real tag names. */ + +static tree +lookup_tag_reverse (type, name) + tree type; + tree name; +{ + register struct binding_level *level; + + for (level = current_binding_level; level; level = level->level_chain) + { + register tree tail; + for (tail = level->tags; tail; tail = TREE_CHAIN (tail)) + { + if (TREE_VALUE (tail) == type) + { + if (name) + TREE_PURPOSE (tail) = name; + return TREE_PURPOSE (tail); + } + } + } + return NULL_TREE; +} + +/* Lookup TYPE in CONTEXT (a chain of nested types or a FUNCTION_DECL). + Return the type value, or NULL_TREE if not found. */ + +static tree +lookup_nested_type (type, context) + tree type; + tree context; +{ + if (context == NULL_TREE) + return NULL_TREE; + while (context) + { + switch (TREE_CODE (context)) + { + case TYPE_DECL: + { + tree ctype = TREE_TYPE (context); + tree match = value_member (type, CLASSTYPE_TAGS (ctype)); + if (match) + return TREE_VALUE (match); + context = DECL_CONTEXT (context); + + /* When we have a nested class whose member functions have + local types (e.g., a set of enums), we'll arrive here + with the DECL_CONTEXT as the actual RECORD_TYPE node for + the enclosing class. Instead, we want to make sure we + come back in here with the TYPE_DECL, not the RECORD_TYPE. */ + if (context && TREE_CODE (context) == RECORD_TYPE) + context = TREE_CHAIN (context); + } + break; + case FUNCTION_DECL: + if (TYPE_NAME (type) && TYPE_IDENTIFIER (type)) + return lookup_name (TYPE_IDENTIFIER (type), 1); + return NULL_TREE; + default: + my_friendly_abort (12); + } + } + return NULL_TREE; +} + +/* Look up NAME in the NAMESPACE. */ + +tree +lookup_namespace_name (namespace, name) + tree namespace, name; +{ + struct tree_binding _b; + tree val; + + my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370); + + if (TREE_CODE (name) == NAMESPACE_DECL) + /* This happens for A::B when B is a namespace. */ + return name; + else if (TREE_CODE (name) == TEMPLATE_DECL) + { + /* This happens for A::B where B is a template, and there are no + template arguments. */ + cp_error ("invalid use of `%D'", name); + return error_mark_node; + } + + namespace = ORIGINAL_NAMESPACE (namespace); + + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373); + + val = binding_init (&_b); + if (!qualified_lookup_using_namespace (name, namespace, val, 0)) + return error_mark_node; + + if (BINDING_VALUE (val)) + { + val = BINDING_VALUE (val); + + /* If we have a single function from a using decl, pull it out. */ + if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val)) + val = OVL_FUNCTION (val); + return val; + } + + cp_error ("`%D' undeclared in namespace `%D'", name, namespace); + return error_mark_node; +} + +/* Hash a TYPENAME_TYPE. K is really of type `tree'. */ + +static unsigned long +typename_hash (k) + hash_table_key k; +{ + unsigned long hash; + tree t; + + t = (tree) k; + hash = (((unsigned long) TYPE_CONTEXT (t)) + ^ ((unsigned long) DECL_NAME (TYPE_NAME (t)))); + + return hash; +} + +/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */ + +static boolean +typename_compare (k1, k2) + hash_table_key k1; + hash_table_key k2; +{ + tree t1; + tree t2; + tree d1; + tree d2; + + t1 = (tree) k1; + t2 = (tree) k2; + d1 = TYPE_NAME (t1); + d2 = TYPE_NAME (t2); + + return (DECL_NAME (d1) == DECL_NAME (d2) + && same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2)) + && ((TREE_TYPE (t1) != NULL_TREE) + == (TREE_TYPE (t2) != NULL_TREE)) + && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) + && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2)); +} + +/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is + the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE + is non-NULL, this type is being created by the implicit typename + extension, and BASE_TYPE is a type named `t' in some base class of + `T' which depends on template parameters. + + Returns the new TYPENAME_TYPE. */ + +tree +build_typename_type (context, name, fullname, base_type) + tree context; + tree name; + tree fullname; + tree base_type; +{ + tree t; + tree d; + struct hash_entry* e; + + static struct hash_table ht; + + push_obstacks (&permanent_obstack, &permanent_obstack); + + if (!ht.table + && !hash_table_init (&ht, &hash_newfunc, &typename_hash, + &typename_compare)) + fatal ("virtual memory exhausted"); + + /* The FULLNAME needs to exist for the life of the hash table, i.e., + for the entire compilation. */ + if (!TREE_PERMANENT (fullname)) + fullname = copy_to_permanent (fullname); + + /* Build the TYPENAME_TYPE. */ + t = make_lang_type (TYPENAME_TYPE); + TYPE_CONTEXT (t) = FROB_CONTEXT (context); + TYPENAME_TYPE_FULLNAME (t) = fullname; + TREE_TYPE (t) = base_type; + + /* Build the corresponding TYPE_DECL. */ + d = build_decl (TYPE_DECL, name, t); + TYPE_NAME (TREE_TYPE (d)) = d; + TYPE_STUB_DECL (TREE_TYPE (d)) = d; + DECL_CONTEXT (d) = FROB_CONTEXT (context); + DECL_ARTIFICIAL (d) = 1; + + /* See if we already have this type. */ + e = hash_lookup (&ht, t, /*create=*/false, /*copy=*/0); + if (e) + { + /* This will free not only TREE_TYPE, but the lang-specific data + and the TYPE_DECL as well. */ + obstack_free (&permanent_obstack, t); + t = (tree) e->key; + } + else + /* Insert the type into the table. */ + hash_lookup (&ht, t, /*create=*/true, /*copy=*/0); + + pop_obstacks (); + + return t; +} + +tree +make_typename_type (context, name) + tree context, name; +{ + tree t; + tree fullname; + + if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') + { + if (!(TYPE_LANG_SPECIFIC (name) + && (CLASSTYPE_IS_TEMPLATE (name) + || CLASSTYPE_USE_TEMPLATE (name)))) + name = TYPE_IDENTIFIER (name); + else + /* Create a TEMPLATE_ID_EXPR for the type. */ + name = build_nt (TEMPLATE_ID_EXPR, + CLASSTYPE_TI_TEMPLATE (name), + CLASSTYPE_TI_ARGS (name)); + } + else if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + + fullname = name; + + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + name = TREE_OPERAND (name, 0); + if (TREE_CODE (name) == TEMPLATE_DECL) + name = TREE_OPERAND (fullname, 0) = DECL_NAME (name); + } + if (TREE_CODE (name) != IDENTIFIER_NODE) + my_friendly_abort (2000); + + if (TREE_CODE (context) == NAMESPACE_DECL) + { + /* We can get here from typename_sub0 in the explicit_template_type + expansion. Just fail. */ + cp_error ("no class template named `%#T' in `%#T'", + name, context); + return error_mark_node; + } + + if (! uses_template_parms (context) + || currently_open_class (context)) + { + if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR) + { + tree tmpl = NULL_TREE; + if (IS_AGGR_TYPE (context)) + tmpl = lookup_field (context, name, 0, 0); + if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl)) + { + cp_error ("no class template named `%#T' in `%#T'", + name, context); + return error_mark_node; + } + + return lookup_template_class (tmpl, + TREE_OPERAND (fullname, 1), + NULL_TREE, context, + /*entering_scope=*/0); + } + else + { + if (IS_AGGR_TYPE (context)) + t = lookup_field (context, name, 0, 1); + else + { + cp_error ("no type named `%#T' in `%#T'", name, context); + return error_mark_node; + } + + if (t) + return TREE_TYPE (t); + } + } + + /* If the CONTEXT is not a template type, then either the field is + there now or its never going to be. */ + if (!uses_template_parms (context) && !t) + { + cp_error ("no type named `%#T' in `%#T'", name, context); + return error_mark_node; + } + + + return build_typename_type (context, name, fullname, NULL_TREE); +} + +/* Select the right _DECL from multiple choices. */ + +static tree +select_decl (binding, flags) + tree binding; + int flags; +{ + tree val; + val = BINDING_VALUE (binding); + if (LOOKUP_NAMESPACES_ONLY (flags)) + { + /* We are not interested in types. */ + if (val && TREE_CODE (val) == NAMESPACE_DECL) + return val; + return NULL_TREE; + } + + /* If we could have a type and + we have nothing or we need a type and have none. */ + if (BINDING_TYPE (binding) + && (!val || ((flags & LOOKUP_PREFER_TYPES) + && TREE_CODE (val) != TYPE_DECL))) + val = TYPE_STUB_DECL (BINDING_TYPE (binding)); + /* Don't return non-types if we really prefer types. */ + else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL + && (TREE_CODE (val) != TEMPLATE_DECL + || !DECL_CLASS_TEMPLATE_P (val))) + val = NULL_TREE; + + return val; +} + +/* Unscoped lookup of a global, iterate over namespaces, considering + using namespace statements. */ + +static tree +unqualified_namespace_lookup (name, flags) + tree name; + int flags; +{ + struct tree_binding _binding; + tree b = binding_init (&_binding); + tree initial = current_decl_namespace(); + tree scope = initial; + tree siter; + struct binding_level *level; + tree val = NULL_TREE; + + while (!val) + { + val = binding_for_name (name, scope); + + /* Initialize binding for this context. */ + BINDING_VALUE (b) = BINDING_VALUE (val); + BINDING_TYPE (b) = BINDING_TYPE (val); + + /* Add all _DECLs seen through local using-directives. */ + for (level = current_binding_level; + !level->namespace_p; + level = level->level_chain) + if (!lookup_using_namespace (name, b, level->using_directives, + scope, flags)) + /* Give up because of error. */ + return error_mark_node; + + /* Add all _DECLs seen through global using-directives. */ + /* XXX local and global using lists should work equally. */ + siter = initial; + while (1) + { + if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter), + scope, flags)) + /* Give up because of error. */ + return error_mark_node; + if (siter == scope) break; + siter = CP_DECL_CONTEXT (siter); + } + + val = select_decl (b, flags); + if (scope == global_namespace) + break; + scope = CP_DECL_CONTEXT (scope); + } + return val; +} + +/* Combine prefer_type and namespaces_only into flags. */ + +static int +lookup_flags (prefer_type, namespaces_only) + int prefer_type, namespaces_only; +{ + if (namespaces_only) + return LOOKUP_PREFER_NAMESPACES; + if (prefer_type > 1) + return LOOKUP_PREFER_TYPES; + if (prefer_type > 0) + return LOOKUP_PREFER_BOTH; + return 0; +} + +/* Given a lookup that returned VAL, use FLAGS to decide if we want to + ignore it or not. Subroutine of lookup_name_real. */ + +static tree +qualify_lookup (val, flags) + tree val; + int flags; +{ + if (val == NULL_TREE) + return val; + if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL) + return val; + if ((flags & LOOKUP_PREFER_TYPES) + && (TREE_CODE (val) == TYPE_DECL + || ((flags & LOOKUP_TEMPLATES_EXPECTED) + && DECL_CLASS_TEMPLATE_P (val)))) + return val; + if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES)) + return NULL_TREE; + return val; +} + +/* Any other BINDING overrides an implicit TYPENAME. Warn about + that. */ + +static void +warn_about_implicit_typename_lookup (typename, binding) + tree typename; + tree binding; +{ + tree subtype = TREE_TYPE (TREE_TYPE (typename)); + tree name = DECL_NAME (typename); + + if (! (TREE_CODE (binding) == TEMPLATE_DECL + && CLASSTYPE_TEMPLATE_INFO (subtype) + && CLASSTYPE_TI_TEMPLATE (subtype) == binding) + && ! (TREE_CODE (binding) == TYPE_DECL + && same_type_p (TREE_TYPE (binding), subtype))) + { + cp_warning ("lookup of `%D' finds `%#D'", + name, binding); + cp_warning (" instead of `%D' from dependent base class", + typename); + cp_warning (" (use `typename %T::%D' if that's what you meant)", + constructor_name (current_class_type), name); + } +} + +/* Look up NAME in the current binding level and its superiors in the + namespace of variables, functions and typedefs. Return a ..._DECL + node of some kind representing its definition if there is only one + such declaration, or return a TREE_LIST with all the overloaded + definitions if there are many, or return 0 if it is undefined. + + If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces. + If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces). + If PREFER_TYPE is -2, we're being called from yylex(). (UGLY) + Otherwise we prefer non-TYPE_DECLs. + + If NONCLASS is non-zero, we don't look for the NAME in class scope, + using IDENTIFIER_CLASS_VALUE. */ + +static tree +lookup_name_real (name, prefer_type, nonclass, namespaces_only) + tree name; + int prefer_type, nonclass, namespaces_only; +{ + tree t; + tree val = NULL_TREE; + int yylex = 0; + tree from_obj = NULL_TREE; + int flags; + int val_is_implicit_typename = 0; + + /* Hack: copy flag set by parser, if set. */ + if (only_namespace_names) + namespaces_only = 1; + + if (prefer_type == -2) + { + extern int looking_for_typename; + tree type = NULL_TREE; + + yylex = 1; + prefer_type = looking_for_typename; + + flags = lookup_flags (prefer_type, namespaces_only); + /* If the next thing is '<', class templates are types. */ + if (looking_for_template) + flags |= LOOKUP_TEMPLATES_EXPECTED; + + /* std:: becomes :: for now. */ + if (got_scope == std_node) + got_scope = void_type_node; + + if (got_scope) + type = got_scope; + else if (got_object != error_mark_node) + type = got_object; + + if (type) + { + if (type == error_mark_node) + return error_mark_node; + if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type)) + type = TREE_TYPE (type); + + if (TYPE_P (type)) + type = complete_type (type); + + if (TREE_CODE (type) == VOID_TYPE) + type = global_namespace; + if (TREE_CODE (type) == NAMESPACE_DECL) + { + struct tree_binding b; + val = binding_init (&b); + flags |= LOOKUP_COMPLAIN; + if (!qualified_lookup_using_namespace (name, type, val, flags)) + return NULL_TREE; + val = select_decl (val, flags); + } + else if (! IS_AGGR_TYPE (type) + || TREE_CODE (type) == TEMPLATE_TYPE_PARM + || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM + || TREE_CODE (type) == TYPENAME_TYPE) + /* Someone else will give an error about this if needed. */ + val = NULL_TREE; + else if (type == current_class_type) + val = IDENTIFIER_CLASS_VALUE (name); + else + val = lookup_member (type, name, 0, prefer_type); + } + else + val = NULL_TREE; + + if (got_scope) + goto done; + else if (got_object && val) + from_obj = val; + } + else + { + flags = lookup_flags (prefer_type, namespaces_only); + /* If we're not parsing, we need to complain. */ + flags |= LOOKUP_COMPLAIN; + } + + /* First, look in non-namespace scopes. */ + for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t)) + { + tree binding; + + if (!LOCAL_BINDING_P (t) && nonclass) + /* We're not looking for class-scoped bindings, so keep going. */ + continue; + + /* If this is the kind of thing we're looking for, we're done. */ + if (qualify_lookup (BINDING_VALUE (t), flags)) + binding = BINDING_VALUE (t); + else if ((flags & LOOKUP_PREFER_TYPES) + && qualify_lookup (BINDING_TYPE (t), flags)) + binding = BINDING_TYPE (t); + else + binding = NULL_TREE; + + if (binding + && (!val || !(TREE_CODE (binding) == TYPE_DECL + && IMPLICIT_TYPENAME_P (TREE_TYPE (binding))))) + { + if (val_is_implicit_typename && !yylex) + warn_about_implicit_typename_lookup (val, binding); + val = binding; + val_is_implicit_typename + = (TREE_CODE (val) == TYPE_DECL + && IMPLICIT_TYPENAME_P (TREE_TYPE (val))); + if (!val_is_implicit_typename) + break; + } + } + + /* Now lookup in namespace scopes. */ + if (!val || val_is_implicit_typename) + { + t = unqualified_namespace_lookup (name, flags); + if (t) + { + if (val_is_implicit_typename && !yylex) + warn_about_implicit_typename_lookup (val, t); + val = t; + } + } + + done: + if (val) + { + /* This should only warn about types used in qualified-ids. */ + if (from_obj && from_obj != val) + { + if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL + && TREE_CODE (val) == TYPE_DECL + && TREE_TYPE (from_obj) != TREE_TYPE (val)) + { + cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%#T')", + name, got_object, TREE_TYPE (from_obj)); + cp_pedwarn (" does not match lookup in the current scope (`%#T')", + TREE_TYPE (val)); + } + + /* We don't change val to from_obj if got_object depends on + template parms because that breaks implicit typename for + destructor calls. */ + if (! uses_template_parms (got_object)) + val = from_obj; + } + + /* If we have a single function from a using decl, pull it out. */ + if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val)) + val = OVL_FUNCTION (val); + } + else if (from_obj) + val = from_obj; + + return val; +} + +tree +lookup_name_nonclass (name) + tree name; +{ + return lookup_name_real (name, 0, 1, 0); +} + +tree +lookup_function_nonclass (name, args) + tree name; + tree args; +{ + return lookup_arg_dependent (name, lookup_name_nonclass (name), args); +} + +tree +lookup_name_namespace_only (name) + tree name; +{ + /* type-or-namespace, nonclass, namespace_only */ + return lookup_name_real (name, 1, 1, 1); +} + +tree +lookup_name (name, prefer_type) + tree name; + int prefer_type; +{ + return lookup_name_real (name, prefer_type, 0, 0); +} + +/* Similar to `lookup_name' but look only in the innermost non-class + binding level. */ + +tree +lookup_name_current_level (name) + tree name; +{ + struct binding_level *b; + tree t = NULL_TREE; + + b = current_binding_level; + while (b->parm_flag == 2) + b = b->level_chain; + + if (b->namespace_p) + { + t = IDENTIFIER_NAMESPACE_VALUE (name); + + /* extern "C" function() */ + if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST) + t = TREE_VALUE (t); + } + else if (IDENTIFIER_BINDING (name) + && LOCAL_BINDING_P (IDENTIFIER_BINDING (name))) + { + while (1) + { + if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b) + return IDENTIFIER_VALUE (name); + + if (b->keep == 2) + b = b->level_chain; + else + break; + } + } + + return t; +} + +/* Like lookup_name_current_level, but for types. */ + +tree +lookup_type_current_level (name) + tree name; +{ + register tree t = NULL_TREE; + + my_friendly_assert (! current_binding_level->namespace_p, 980716); + + if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE + && REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node) + { + struct binding_level *b = current_binding_level; + while (1) + { + if (purpose_member (name, b->type_shadowed)) + return REAL_IDENTIFIER_TYPE_VALUE (name); + if (b->keep == 2) + b = b->level_chain; + else + break; + } + } + + return t; +} + +void +begin_only_namespace_names () +{ + only_namespace_names = 1; +} + +void +end_only_namespace_names () +{ + only_namespace_names = 0; +} + +/* Arrange for the user to get a source line number, even when the + compiler is going down in flames, so that she at least has a + chance of working around problems in the compiler. We used to + call error(), but that let the segmentation fault continue + through; now, it's much more passive by asking them to send the + maintainers mail about the problem. */ + +static void +signal_catch (sig) + int sig ATTRIBUTE_UNUSED; +{ + signal (SIGSEGV, SIG_DFL); +#ifdef SIGIOT + signal (SIGIOT, SIG_DFL); +#endif +#ifdef SIGILL + signal (SIGILL, SIG_DFL); +#endif +#ifdef SIGABRT + signal (SIGABRT, SIG_DFL); +#endif +#ifdef SIGBUS + signal (SIGBUS, SIG_DFL); +#endif + my_friendly_abort (0); +} + +#if 0 +/* Unused -- brendan 970107 */ +/* Array for holding types considered "built-in". These types + are output in the module in which `main' is defined. */ +static tree *builtin_type_tdescs_arr; +static int builtin_type_tdescs_len, builtin_type_tdescs_max; +#endif + +/* Push the declarations of builtin types into the namespace. + RID_INDEX, if < RID_MAX is the index of the builtin type + in the array RID_POINTERS. NAME is the name used when looking + up the builtin type. TYPE is the _TYPE node for the builtin type. */ + +static void +record_builtin_type (rid_index, name, type) + enum rid rid_index; + const char *name; + tree type; +{ + tree rname = NULL_TREE, tname = NULL_TREE; + tree tdecl = NULL_TREE; + + if ((int) rid_index < (int) RID_MAX) + rname = ridpointers[(int) rid_index]; + if (name) + tname = get_identifier (name); + + TYPE_BUILT_IN (type) = 1; + + if (tname) + { + tdecl = pushdecl (build_decl (TYPE_DECL, tname, type)); + set_identifier_type_value (tname, NULL_TREE); + if ((int) rid_index < (int) RID_MAX) + /* Built-in types live in the global namespace. */ + SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl); + } + if (rname != NULL_TREE) + { + if (tname != NULL_TREE) + { + set_identifier_type_value (rname, NULL_TREE); + SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl); + } + else + { + tdecl = pushdecl (build_decl (TYPE_DECL, rname, type)); + set_identifier_type_value (rname, NULL_TREE); + } + } +} + +/* Record one of the standard Java types. + * Declare it as having the given NAME. + * If SIZE > 0, it is the size of one of the integral types; + * otherwise it is the negative of the size of one of the other types. */ + +static tree +record_builtin_java_type (name, size) + const char *name; + int size; +{ + tree type, decl; + if (size > 0) + type = make_signed_type (size); + else if (size > -32) + { /* "__java_char" or ""__java_boolean". */ + type = make_unsigned_type (-size); + /*if (size == -1) TREE_SET_CODE (type, BOOLEAN_TYPE);*/ + } + else + { /* "__java_float" or ""__java_double". */ + type = make_node (REAL_TYPE); + TYPE_PRECISION (type) = - size; + layout_type (type); + } + record_builtin_type (RID_MAX, name, type); + decl = TYPE_NAME (type); + + /* Suppress generate debug symbol entries for these types, + since for normal C++ they are just clutter. + However, push_lang_context undoes this if extern "Java" is seen. */ + DECL_IGNORED_P (decl) = 1; + + TYPE_FOR_JAVA (type) = 1; + return type; +} + +/* Push a type into the namespace so that the back-ends ignore it. */ + +static void +record_unknown_type (type, name) + tree type; + const char *name; +{ + tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type)); + /* Make sure the "unknown type" typedecl gets ignored for debug info. */ + DECL_IGNORED_P (decl) = 1; + TYPE_DECL_SUPPRESS_DEBUG (decl) = 1; + TYPE_SIZE (type) = TYPE_SIZE (void_type_node); + TYPE_ALIGN (type) = 1; + TYPE_MODE (type) = TYPE_MODE (void_type_node); +} + +/* Push overloaded decl, in global scope, with one argument so it + can be used as a callback from define_function. */ + +static void +push_overloaded_decl_1 (x) + tree x; +{ + push_overloaded_decl (x, PUSH_GLOBAL); +} + +#ifdef __GNUC__ +__inline +#endif +tree +auto_function (name, type, code) + tree name, type; + enum built_in_function code; +{ + return define_function + (IDENTIFIER_POINTER (name), type, code, push_overloaded_decl_1, + IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type), + 0))); +} + +/* Create the predefined scalar types of C, + and some nodes representing standard constants (0, 1, (void *)0). + Initialize the global binding level. + Make definitions for built-in primitive functions. */ + +void +init_decl_processing () +{ + register tree endlink, int_endlink, double_endlink, unsigned_endlink; + tree fields[20]; + /* Data type of memcpy. */ + tree memcpy_ftype, strlen_ftype; + int wchar_type_size; + tree temp; + tree array_domain_type; + tree vb_off_identifier = NULL_TREE; + /* Function type `char *(char *, char *)' and similar ones */ + tree string_ftype_ptr_ptr, int_ftype_string_string; + tree sizetype_endlink; + tree ptr_ftype, ptr_ftype_unsigned, ptr_ftype_sizetype; + tree void_ftype, void_ftype_int, void_ftype_ptr; + + /* Have to make these distinct before we try using them. */ + lang_name_cplusplus = get_identifier ("C++"); + lang_name_c = get_identifier ("C"); + lang_name_java = get_identifier ("Java"); + + /* Enter the global namespace. */ + my_friendly_assert (global_namespace == NULL_TREE, 375); + my_friendly_assert (current_lang_name == NULL_TREE, 375); + current_lang_name = lang_name_cplusplus; + push_namespace (get_identifier ("::")); + global_namespace = current_namespace; + current_lang_name = NULL_TREE; + + if (flag_strict_prototype == 2) + flag_strict_prototype = pedantic; + if (! flag_permissive && ! pedantic) + flag_pedantic_errors = 1; + + strict_prototypes_lang_c = flag_strict_prototype; + + /* Initially, C. */ + current_lang_name = lang_name_c; + + current_function_decl = NULL_TREE; + named_labels = NULL_TREE; + named_label_uses = NULL; + current_binding_level = NULL_BINDING_LEVEL; + free_binding_level = NULL_BINDING_LEVEL; + + /* Because most segmentation signals can be traced back into user + code, catch them and at least give the user a chance of working + around compiler bugs. */ + signal (SIGSEGV, signal_catch); + + /* We will also catch aborts in the back-end through signal_catch and + give the user a chance to see where the error might be, and to defeat + aborts in the back-end when there have been errors previously in their + code. */ +#ifdef SIGIOT + signal (SIGIOT, signal_catch); +#endif +#ifdef SIGILL + signal (SIGILL, signal_catch); +#endif +#ifdef SIGABRT + signal (SIGABRT, signal_catch); +#endif +#ifdef SIGBUS + signal (SIGBUS, signal_catch); +#endif + + gcc_obstack_init (&decl_obstack); + + /* Must lay these out before anything else gets laid out. */ + error_mark_node = make_node (ERROR_MARK); + TREE_PERMANENT (error_mark_node) = 1; + TREE_TYPE (error_mark_node) = error_mark_node; + error_mark_list = build_tree_list (error_mark_node, error_mark_node); + TREE_TYPE (error_mark_list) = error_mark_node; + + /* Make the binding_level structure for global names. */ + pushlevel (0); + global_binding_level = current_binding_level; + /* The global level is the namespace level of ::. */ + NAMESPACE_LEVEL (global_namespace) = global_binding_level; + declare_namespace_level (); + + this_identifier = get_identifier (THIS_NAME); + in_charge_identifier = get_identifier (IN_CHARGE_NAME); + vlist_identifier = get_identifier (VLIST_NAME); + ctor_identifier = get_identifier (CTOR_NAME); + dtor_identifier = get_identifier (DTOR_NAME); + pfn_identifier = get_identifier (VTABLE_PFN_NAME); + index_identifier = get_identifier (VTABLE_INDEX_NAME); + delta_identifier = get_identifier (VTABLE_DELTA_NAME); + delta2_identifier = get_identifier (VTABLE_DELTA2_NAME); + pfn_or_delta2_identifier = get_identifier ("__pfn_or_delta2"); + if (flag_handle_signatures) + { + tag_identifier = get_identifier (SIGTABLE_TAG_NAME); + vb_off_identifier = get_identifier (SIGTABLE_VB_OFF_NAME); + vt_off_identifier = get_identifier (SIGTABLE_VT_OFF_NAME); + } + + /* Define `int' and `char' first so that dbx will output them first. */ + + integer_type_node = make_signed_type (INT_TYPE_SIZE); + record_builtin_type (RID_INT, NULL_PTR, integer_type_node); + + /* Define `char', which is like either `signed char' or `unsigned char' + but not the same as either. */ + + char_type_node + = (flag_signed_char + ? make_signed_type (CHAR_TYPE_SIZE) + : make_unsigned_type (CHAR_TYPE_SIZE)); + record_builtin_type (RID_CHAR, "char", char_type_node); + + /* `signed' is the same as `int' */ + record_builtin_type (RID_SIGNED, NULL_PTR, integer_type_node); + + long_integer_type_node = make_signed_type (LONG_TYPE_SIZE); + record_builtin_type (RID_LONG, "long int", long_integer_type_node); + + unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE); + record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node); + + long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE); + record_builtin_type (RID_MAX, "long unsigned int", long_unsigned_type_node); + record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node); + + long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE); + record_builtin_type (RID_MAX, "long long int", long_long_integer_type_node); + + long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE); + record_builtin_type (RID_MAX, "long long unsigned int", + long_long_unsigned_type_node); + record_builtin_type (RID_MAX, "long long unsigned", + long_long_unsigned_type_node); + + short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); + record_builtin_type (RID_SHORT, "short int", short_integer_type_node); + short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); + record_builtin_type (RID_MAX, "short unsigned int", short_unsigned_type_node); + record_builtin_type (RID_MAX, "unsigned short", short_unsigned_type_node); + + /* `unsigned long' is the standard type for sizeof. + Note that stddef.h uses `unsigned long', + and this must agree, even if long and int are the same size. */ + set_sizetype + (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)))); + + ptrdiff_type_node + = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE))); + + /* Define both `signed char' and `unsigned char'. */ + signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); + record_builtin_type (RID_MAX, "signed char", signed_char_type_node); + unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE); + record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node); + + /* These are types that type_for_size and type_for_mode use. */ + intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node)); + intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node)); + intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node)); + intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node)); +#if HOST_BITS_PER_WIDE_INT >= 64 + intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode)); + pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node)); +#endif + unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node)); + unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node)); + unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node)); + unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node)); +#if HOST_BITS_PER_WIDE_INT >= 64 + unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode)); + pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node)); +#endif + + float_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE; + record_builtin_type (RID_FLOAT, NULL_PTR, float_type_node); + layout_type (float_type_node); + + double_type_node = make_node (REAL_TYPE); + if (flag_short_double) + TYPE_PRECISION (double_type_node) = FLOAT_TYPE_SIZE; + else + TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE; + record_builtin_type (RID_DOUBLE, NULL_PTR, double_type_node); + layout_type (double_type_node); + + long_double_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE; + record_builtin_type (RID_MAX, "long double", long_double_type_node); + layout_type (long_double_type_node); + + complex_integer_type_node = make_node (COMPLEX_TYPE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"), + complex_integer_type_node)); + TREE_TYPE (complex_integer_type_node) = integer_type_node; + layout_type (complex_integer_type_node); + + complex_float_type_node = make_node (COMPLEX_TYPE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"), + complex_float_type_node)); + TREE_TYPE (complex_float_type_node) = float_type_node; + layout_type (complex_float_type_node); + + complex_double_type_node = make_node (COMPLEX_TYPE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"), + complex_double_type_node)); + TREE_TYPE (complex_double_type_node) = double_type_node; + layout_type (complex_double_type_node); + + complex_long_double_type_node = make_node (COMPLEX_TYPE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"), + complex_long_double_type_node)); + TREE_TYPE (complex_long_double_type_node) = long_double_type_node; + layout_type (complex_long_double_type_node); + + java_byte_type_node = record_builtin_java_type ("__java_byte", 8); + java_short_type_node = record_builtin_java_type ("__java_short", 16); + java_int_type_node = record_builtin_java_type ("__java_int", 32); + java_long_type_node = record_builtin_java_type ("__java_long", 64); + java_float_type_node = record_builtin_java_type ("__java_float", -32); + java_double_type_node = record_builtin_java_type ("__java_double", -64); + java_char_type_node = record_builtin_java_type ("__java_char", -16); + java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1); + + integer_zero_node = build_int_2 (0, 0); + TREE_TYPE (integer_zero_node) = integer_type_node; + integer_one_node = build_int_2 (1, 0); + TREE_TYPE (integer_one_node) = integer_type_node; + integer_two_node = build_int_2 (2, 0); + TREE_TYPE (integer_two_node) = integer_type_node; + integer_three_node = build_int_2 (3, 0); + TREE_TYPE (integer_three_node) = integer_type_node; + + boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE); + TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE); + TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0); + TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node; + TYPE_PRECISION (boolean_type_node) = 1; + record_builtin_type (RID_BOOL, "bool", boolean_type_node); + boolean_false_node = build_int_2 (0, 0); + TREE_TYPE (boolean_false_node) = boolean_type_node; + boolean_true_node = build_int_2 (1, 0); + TREE_TYPE (boolean_true_node) = boolean_type_node; + + /* These are needed by stor-layout.c. */ + size_zero_node = size_int (0); + size_one_node = size_int (1); + + signed_size_zero_node = build_int_2 (0, 0); + TREE_TYPE (signed_size_zero_node) = make_signed_type (TYPE_PRECISION (sizetype)); + + void_type_node = make_node (VOID_TYPE); + record_builtin_type (RID_VOID, NULL_PTR, void_type_node); + layout_type (void_type_node); /* Uses integer_zero_node. */ + void_list_node = build_tree_list (NULL_TREE, void_type_node); + TREE_PARMLIST (void_list_node) = 1; + + null_pointer_node = build_int_2 (0, 0); + TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node); + layout_type (TREE_TYPE (null_pointer_node)); + + /* Used for expressions that do nothing, but are not errors. */ + void_zero_node = build_int_2 (0, 0); + TREE_TYPE (void_zero_node) = void_type_node; + + string_type_node = build_pointer_type (char_type_node); + const_string_type_node + = build_pointer_type (build_qualified_type (char_type_node, + TYPE_QUAL_CONST)); +#if 0 + record_builtin_type (RID_MAX, NULL_PTR, string_type_node); +#endif + + /* Make a type to be the domain of a few array types + whose domains don't really matter. + 200 is small enough that it always fits in size_t + and large enough that it can hold most function names for the + initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */ + array_domain_type = build_index_type (build_int_2 (200, 0)); + + /* Make a type for arrays of characters. + With luck nothing will ever really depend on the length of this + array type. */ + char_array_type_node + = build_array_type (char_type_node, array_domain_type); + /* Likewise for arrays of ints. */ + int_array_type_node + = build_array_type (integer_type_node, array_domain_type); + + /* This is just some anonymous class type. Nobody should ever + need to look inside this envelope. */ + class_star_type_node = build_pointer_type (make_lang_type (RECORD_TYPE)); + + default_function_type + = build_function_type (integer_type_node, NULL_TREE); + + ptr_type_node = build_pointer_type (void_type_node); + const_ptr_type_node + = build_pointer_type (build_qualified_type (void_type_node, + TYPE_QUAL_CONST)); +#if 0 + record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node); +#endif + + endlink = void_list_node; + int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink); + double_endlink = tree_cons (NULL_TREE, double_type_node, endlink); + unsigned_endlink = tree_cons (NULL_TREE, unsigned_type_node, endlink); + + ptr_ftype = build_function_type (ptr_type_node, NULL_TREE); + ptr_ftype_unsigned = build_function_type (ptr_type_node, unsigned_endlink); + sizetype_endlink = tree_cons (NULL_TREE, sizetype, endlink); + /* We realloc here because sizetype could be int or unsigned. S'ok. */ + ptr_ftype_sizetype = build_function_type (ptr_type_node, sizetype_endlink); + + void_ftype = build_function_type (void_type_node, endlink); + void_ftype_int = build_function_type (void_type_node, int_endlink); + void_ftype_ptr + = build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, endlink)); + void_ftype_ptr + = build_exception_variant (void_ftype_ptr, + tree_cons (NULL_TREE, NULL_TREE, NULL_TREE)); + + float_ftype_float + = build_function_type (float_type_node, + tree_cons (NULL_TREE, float_type_node, endlink)); + + double_ftype_double + = build_function_type (double_type_node, double_endlink); + + ldouble_ftype_ldouble + = build_function_type (long_double_type_node, + tree_cons (NULL_TREE, long_double_type_node, + endlink)); + + double_ftype_double_double + = build_function_type (double_type_node, + tree_cons (NULL_TREE, double_type_node, + double_endlink)); + + int_ftype_int + = build_function_type (integer_type_node, int_endlink); + + long_ftype_long + = build_function_type (long_integer_type_node, + tree_cons (NULL_TREE, long_integer_type_node, + endlink)); + + int_ftype_cptr_cptr_sizet + = build_function_type (integer_type_node, + tree_cons (NULL_TREE, const_ptr_type_node, + tree_cons (NULL_TREE, const_ptr_type_node, + tree_cons (NULL_TREE, + sizetype, + endlink)))); + + string_ftype_ptr_ptr /* strcpy prototype */ + = build_function_type (string_type_node, + tree_cons (NULL_TREE, string_type_node, + tree_cons (NULL_TREE, + const_string_type_node, + endlink))); + + int_ftype_string_string /* strcmp prototype */ + = build_function_type (integer_type_node, + tree_cons (NULL_TREE, const_string_type_node, + tree_cons (NULL_TREE, + const_string_type_node, + endlink))); + + strlen_ftype /* strlen prototype */ + = build_function_type (sizetype, + tree_cons (NULL_TREE, const_string_type_node, + endlink)); + + memcpy_ftype /* memcpy prototype */ + = build_function_type (ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, const_ptr_type_node, + sizetype_endlink))); + + if (flag_huge_objects) + delta_type_node = long_integer_type_node; + else + delta_type_node = short_integer_type_node; + + builtin_function ("__builtin_constant_p", default_function_type, + BUILT_IN_CONSTANT_P, NULL_PTR); + + builtin_return_address_fndecl + = builtin_function ("__builtin_return_address", ptr_ftype_unsigned, + BUILT_IN_RETURN_ADDRESS, NULL_PTR); + + builtin_function ("__builtin_frame_address", ptr_ftype_unsigned, + BUILT_IN_FRAME_ADDRESS, NULL_PTR); + + builtin_function ("__builtin_alloca", ptr_ftype_sizetype, + BUILT_IN_ALLOCA, "alloca"); + builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR); + /* Define alloca, ffs as builtins. + Declare _exit just to mark it as volatile. */ + if (! flag_no_builtin && !flag_no_nonansi_builtin) + { + temp = builtin_function ("alloca", ptr_ftype_sizetype, + BUILT_IN_ALLOCA, NULL_PTR); + /* Suppress error if redefined as a non-function. */ + DECL_BUILT_IN_NONANSI (temp) = 1; + temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR); + /* Suppress error if redefined as a non-function. */ + DECL_BUILT_IN_NONANSI (temp) = 1; + temp = builtin_function ("_exit", void_ftype_int, + NOT_BUILT_IN, NULL_PTR); + TREE_THIS_VOLATILE (temp) = 1; + TREE_SIDE_EFFECTS (temp) = 1; + /* Suppress error if redefined as a non-function. */ + DECL_BUILT_IN_NONANSI (temp) = 1; + } + + builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR); + builtin_function ("__builtin_fabsf", float_ftype_float, BUILT_IN_FABS, + NULL_PTR); + builtin_function ("__builtin_fabs", double_ftype_double, BUILT_IN_FABS, + NULL_PTR); + builtin_function ("__builtin_fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS, + NULL_PTR); + builtin_function ("__builtin_labs", long_ftype_long, + BUILT_IN_LABS, NULL_PTR); + builtin_function ("__builtin_saveregs", ptr_ftype, + BUILT_IN_SAVEREGS, NULL_PTR); + builtin_function ("__builtin_classify_type", default_function_type, + BUILT_IN_CLASSIFY_TYPE, NULL_PTR); + builtin_function ("__builtin_next_arg", ptr_ftype, + BUILT_IN_NEXT_ARG, NULL_PTR); + builtin_function ("__builtin_args_info", int_ftype_int, + BUILT_IN_ARGS_INFO, NULL_PTR); + builtin_function ("__builtin_setjmp", + build_function_type (integer_type_node, + tree_cons (NULL_TREE, ptr_type_node, + endlink)), + BUILT_IN_SETJMP, NULL_PTR); + builtin_function ("__builtin_longjmp", + build_function_type (integer_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, + integer_type_node, + endlink))), + BUILT_IN_LONGJMP, NULL_PTR); + + /* Untyped call and return. */ + builtin_function ("__builtin_apply_args", ptr_ftype, + BUILT_IN_APPLY_ARGS, NULL_PTR); + + temp = tree_cons (NULL_TREE, + build_pointer_type (build_function_type (void_type_node, + NULL_TREE)), + tree_cons (NULL_TREE, ptr_ftype_sizetype, NULL_TREE)); + builtin_function ("__builtin_apply", + build_function_type (ptr_type_node, temp), + BUILT_IN_APPLY, NULL_PTR); + builtin_function ("__builtin_return", void_ftype_ptr, + BUILT_IN_RETURN, NULL_PTR); + + /* Currently under experimentation. */ + builtin_function ("__builtin_memcpy", memcpy_ftype, + BUILT_IN_MEMCPY, "memcpy"); + builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet, + BUILT_IN_MEMCMP, "memcmp"); + builtin_function ("__builtin_strcmp", int_ftype_string_string, + BUILT_IN_STRCMP, "strcmp"); + builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr, + BUILT_IN_STRCPY, "strcpy"); + builtin_function ("__builtin_strlen", strlen_ftype, + BUILT_IN_STRLEN, "strlen"); + builtin_function ("__builtin_sqrtf", float_ftype_float, + BUILT_IN_FSQRT, "sqrtf"); + builtin_function ("__builtin_fsqrt", double_ftype_double, + BUILT_IN_FSQRT, NULL_PTR); + builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble, + BUILT_IN_FSQRT, "sqrtl"); + builtin_function ("__builtin_sinf", float_ftype_float, + BUILT_IN_SIN, "sinf"); + builtin_function ("__builtin_sin", double_ftype_double, + BUILT_IN_SIN, "sin"); + builtin_function ("__builtin_sinl", ldouble_ftype_ldouble, + BUILT_IN_SIN, "sinl"); + builtin_function ("__builtin_cosf", float_ftype_float, + BUILT_IN_COS, "cosf"); + builtin_function ("__builtin_cos", double_ftype_double, + BUILT_IN_COS, "cos"); + builtin_function ("__builtin_cosl", ldouble_ftype_ldouble, + BUILT_IN_COS, "cosl"); + + if (!flag_no_builtin) + { + builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR); + builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, NULL_PTR); + builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR); + builtin_function ("fabsf", float_ftype_float, BUILT_IN_FABS, NULL_PTR); + builtin_function ("fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS, + NULL_PTR); + builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR); + builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, + NULL_PTR); + builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, + NULL_PTR); + builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, + NULL_PTR); + builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, NULL_PTR); + builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT, NULL_PTR); + builtin_function ("sqrt", double_ftype_double, BUILT_IN_FSQRT, NULL_PTR); + builtin_function ("sqrtl", ldouble_ftype_ldouble, BUILT_IN_FSQRT, + NULL_PTR); + builtin_function ("sinf", float_ftype_float, BUILT_IN_SIN, NULL_PTR); + builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR); + builtin_function ("sinl", ldouble_ftype_ldouble, BUILT_IN_SIN, NULL_PTR); + builtin_function ("cosf", float_ftype_float, BUILT_IN_COS, NULL_PTR); + builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR); + builtin_function ("cosl", ldouble_ftype_ldouble, BUILT_IN_COS, NULL_PTR); + + /* Declare these functions volatile + to avoid spurious "control drops through" warnings. */ + temp = builtin_function ("abort", void_ftype, + NOT_BUILT_IN, NULL_PTR); + TREE_THIS_VOLATILE (temp) = 1; + TREE_SIDE_EFFECTS (temp) = 1; + /* Well, these are actually ANSI, but we can't set DECL_BUILT_IN on + them... */ + DECL_BUILT_IN_NONANSI (temp) = 1; + temp = builtin_function ("exit", void_ftype_int, + NOT_BUILT_IN, NULL_PTR); + TREE_THIS_VOLATILE (temp) = 1; + TREE_SIDE_EFFECTS (temp) = 1; + DECL_BUILT_IN_NONANSI (temp) = 1; + } + +#if 0 + /* Support for these has not been written in either expand_builtin + or build_function_call. */ + builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, NULL_PTR); + builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, NULL_PTR); + builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, + NULL_PTR); + builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, + NULL_PTR); + builtin_function ("__builtin_fmod", double_ftype_double_double, + BUILT_IN_FMOD, NULL_PTR); + builtin_function ("__builtin_frem", double_ftype_double_double, + BUILT_IN_FREM, NULL_PTR); + builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, + BUILT_IN_MEMSET, NULL_PTR); + builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, + NULL_PTR); + builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, + NULL_PTR); +#endif + + /* C++ extensions */ + + unknown_type_node = make_node (UNKNOWN_TYPE); + record_unknown_type (unknown_type_node, "unknown type"); + + /* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */ + TREE_TYPE (unknown_type_node) = unknown_type_node; + + TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0); + + /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same + result. */ + TYPE_POINTER_TO (unknown_type_node) = unknown_type_node; + TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node; + + /* This is for handling opaque types in signatures. */ + opaque_type_node = copy_node (ptr_type_node); + TYPE_MAIN_VARIANT (opaque_type_node) = opaque_type_node; + record_builtin_type (RID_MAX, 0, opaque_type_node); + + /* This is special for C++ so functions can be overloaded. */ + wchar_type_node + = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE))); + wchar_type_size = TYPE_PRECISION (wchar_type_node); + signed_wchar_type_node = make_signed_type (wchar_type_size); + unsigned_wchar_type_node = make_unsigned_type (wchar_type_size); + wchar_type_node + = TREE_UNSIGNED (wchar_type_node) + ? unsigned_wchar_type_node + : signed_wchar_type_node; + record_builtin_type (RID_WCHAR, "__wchar_t", wchar_type_node); + + /* Artificial declaration of wchar_t -- can be bashed */ + wchar_decl_node = build_decl (TYPE_DECL, get_identifier ("wchar_t"), + wchar_type_node); + pushdecl (wchar_decl_node); + + /* This is for wide string constants. */ + wchar_array_type_node + = build_array_type (wchar_type_node, array_domain_type); + + if (flag_vtable_thunks) + { + /* Make sure we get a unique function type, so we can give + its pointer type a name. (This wins for gdb.) */ + tree vfunc_type = make_node (FUNCTION_TYPE); + TREE_TYPE (vfunc_type) = integer_type_node; + TYPE_ARG_TYPES (vfunc_type) = NULL_TREE; + layout_type (vfunc_type); + + vtable_entry_type = build_pointer_type (vfunc_type); + } + else + { + vtable_entry_type = make_lang_type (RECORD_TYPE); + fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, + delta_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, + delta_type_node); + fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier, + ptr_type_node); + finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2, + double_type_node); + + /* Make this part of an invisible union. */ + fields[3] = copy_node (fields[2]); + TREE_TYPE (fields[3]) = delta_type_node; + DECL_NAME (fields[3]) = delta2_identifier; + DECL_MODE (fields[3]) = TYPE_MODE (delta_type_node); + DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node); + TREE_UNSIGNED (fields[3]) = 0; + TREE_CHAIN (fields[2]) = fields[3]; + vtable_entry_type = build_qualified_type (vtable_entry_type, + TYPE_QUAL_CONST); + } + record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type); + + vtbl_type_node + = build_cplus_array_type (vtable_entry_type, NULL_TREE); + layout_type (vtbl_type_node); + vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST); + record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node); + vtbl_ptr_type_node = build_pointer_type (vtable_entry_type); + layout_type (vtbl_ptr_type_node); + record_builtin_type (RID_MAX, NULL_PTR, vtbl_ptr_type_node); + + if (flag_vtable_thunks) + { + /* We need vlists only when using thunks; otherwise leave them + as NULL_TREE. That way, it doesn't get into the way of the + mangling. */ + vlist_type_node = build_pointer_type (vtbl_ptr_type_node); + vlist_zero_node = build_int_2 (0, 0); + TREE_TYPE (vlist_zero_node) = vlist_type_node; + } + + /* Simplify life by making a "sigtable_entry_type". Give its + fields names so that the debugger can use them. */ + + if (flag_handle_signatures) + { + sigtable_entry_type = make_lang_type (RECORD_TYPE); + fields[0] = build_lang_field_decl (FIELD_DECL, tag_identifier, + delta_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, vb_off_identifier, + delta_type_node); + fields[2] = build_lang_field_decl (FIELD_DECL, delta_identifier, + delta_type_node); + fields[3] = build_lang_field_decl (FIELD_DECL, index_identifier, + delta_type_node); + fields[4] = build_lang_field_decl (FIELD_DECL, pfn_identifier, + ptr_type_node); + + /* Set the alignment to the max of the alignment of ptr_type_node and + delta_type_node. Double alignment wastes a word on the Sparc. */ + finish_builtin_type (sigtable_entry_type, SIGTABLE_PTR_TYPE, fields, 4, + (TYPE_ALIGN (ptr_type_node) > TYPE_ALIGN (delta_type_node)) + ? ptr_type_node + : delta_type_node); + + /* Make this part of an invisible union. */ + fields[5] = copy_node (fields[4]); + TREE_TYPE (fields[5]) = delta_type_node; + DECL_NAME (fields[5]) = vt_off_identifier; + DECL_MODE (fields[5]) = TYPE_MODE (delta_type_node); + DECL_SIZE (fields[5]) = TYPE_SIZE (delta_type_node); + TREE_UNSIGNED (fields[5]) = 0; + TREE_CHAIN (fields[4]) = fields[5]; + + sigtable_entry_type = build_qualified_type (sigtable_entry_type, + TYPE_QUAL_CONST); + record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type); + } + + std_node = build_decl (NAMESPACE_DECL, + get_identifier (flag_honor_std ? "fake std":"std"), + void_type_node); + pushdecl (std_node); + + global_type_node = make_node (LANG_TYPE); + record_unknown_type (global_type_node, "global type"); + + /* Now, C++. */ + current_lang_name = lang_name_cplusplus; + + { + tree bad_alloc_type_node, newtype, deltype; + if (flag_honor_std) + push_namespace (get_identifier ("std")); + bad_alloc_type_node = xref_tag + (class_type_node, get_identifier ("bad_alloc"), 1); + if (flag_honor_std) + pop_namespace (); + newtype = build_exception_variant + (ptr_ftype_sizetype, build_tree_list (NULL_TREE, bad_alloc_type_node)); + deltype = build_exception_variant + (void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE)); + auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN); + auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN); + global_delete_fndecl + = auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN); + auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN); + } + + abort_fndecl + = define_function ("__pure_virtual", void_ftype, + NOT_BUILT_IN, 0, 0); + + /* Perform other language dependent initializations. */ + init_class_processing (); + init_init_processing (); + init_search_processing (); + if (flag_rtti) + init_rtti_processing (); + + if (flag_exceptions) + init_exception_processing (); + if (flag_no_inline) + { + flag_inline_functions = 0; + } + + if (! supports_one_only ()) + flag_weak = 0; + + /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */ + declare_function_name (); + + /* Prepare to check format strings against argument lists. */ + init_function_format_info (); + + /* Show we use EH for cleanups. */ + using_eh_for_cleanups (); + + print_error_function = lang_print_error_function; + lang_get_alias_set = &c_get_alias_set; + valid_lang_attribute = cp_valid_lang_attribute; + + /* Maintain consistency. Perhaps we should just complain if they + say -fwritable-strings? */ + if (flag_writable_strings) + flag_const_strings = 0; +} + +/* Function to print any language-specific context for an error message. */ + +static void +lang_print_error_function (file) + char *file; +{ + default_print_error_function (file); + maybe_print_template_context (); +} + +/* Make a definition for a builtin function named NAME and whose data type + is TYPE. TYPE should be a function type with argument types. + FUNCTION_CODE tells later passes how to compile calls to this function. + See tree.h for its possible values. + + If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME, + the name to be called if we can't opencode the function. */ + +tree +define_function (name, type, function_code, pfn, library_name) + const char *name; + tree type; + enum built_in_function function_code; + void (*pfn) PROTO((tree)); + const char *library_name; +{ + tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + + my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392); + DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); + + /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME, + we cannot change DECL_ASSEMBLER_NAME until we have installed this + function in the namespace. */ + if (pfn) (*pfn) (decl); + if (library_name) + DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name); + make_function_rtl (decl); + if (function_code != NOT_BUILT_IN) + { + DECL_BUILT_IN (decl) = 1; + DECL_FUNCTION_CODE (decl) = function_code; + } + return decl; +} + +/* When we call finish_struct for an anonymous union, we create + default copy constructors and such. But, an anonymous union + shouldn't have such things; this function undoes the damage to the + anonymous union type T. + + (The reason that we create the synthesized methods is that we don't + distinguish `union { int i; }' from `typedef union { int i; } U'. + The first is an anonymous union; the second is just an ordinary + union type.) */ + +void +fixup_anonymous_union (t) + tree t; +{ + tree *q; + + /* Wipe out memory of synthesized methods */ + TYPE_HAS_CONSTRUCTOR (t) = 0; + TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0; + TYPE_HAS_INIT_REF (t) = 0; + TYPE_HAS_CONST_INIT_REF (t) = 0; + TYPE_HAS_ASSIGN_REF (t) = 0; + TYPE_HAS_CONST_ASSIGN_REF (t) = 0; + + /* Splice the implicitly generated functions out of the TYPE_METHODS + list. */ + q = &TYPE_METHODS (t); + while (*q) + { + if (DECL_ARTIFICIAL (*q)) + *q = TREE_CHAIN (*q); + else + q = &TREE_CHAIN (*q); + } + + /* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have + function members. */ + if (TYPE_METHODS (t)) + error ("an anonymous union cannot have function members"); +} + +/* Make sure that a declaration with no declarator is well-formed, i.e. + just defines a tagged type or anonymous union. + + Returns the type defined, if any. */ + +tree +check_tag_decl (declspecs) + tree declspecs; +{ + int found_type = 0; + tree ob_modifier = NULL_TREE; + register tree link; + register tree t = NULL_TREE; + + for (link = declspecs; link; link = TREE_CHAIN (link)) + { + register tree value = TREE_VALUE (link); + + if (TYPE_P (value)) + { + ++found_type; + + if (IS_AGGR_TYPE (value) || TREE_CODE (value) == ENUMERAL_TYPE) + { + my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261); + t = value; + } + } + else if (value == ridpointers[(int) RID_FRIEND]) + { + if (current_class_type == NULL_TREE + || current_scope () != current_class_type) + ob_modifier = value; + } + else if (value == ridpointers[(int) RID_STATIC] + || value == ridpointers[(int) RID_EXTERN] + || value == ridpointers[(int) RID_AUTO] + || value == ridpointers[(int) RID_REGISTER] + || value == ridpointers[(int) RID_INLINE] + || value == ridpointers[(int) RID_VIRTUAL] + || value == ridpointers[(int) RID_CONST] + || value == ridpointers[(int) RID_VOLATILE] + || value == ridpointers[(int) RID_EXPLICIT]) + ob_modifier = value; + } + + if (found_type > 1) + error ("multiple types in one declaration"); + + /* Inside a class, we might be in a friend or access declaration. + Until we have a good way of detecting the latter, don't warn. */ + if (t == NULL_TREE && ! current_class_type) + pedwarn ("declaration does not declare anything"); + + /* Check for an anonymous union. We're careful + accessing TYPE_IDENTIFIER because some built-in types, like + pointer-to-member types, do not have TYPE_NAME. */ + else if (t && TREE_CODE (t) == UNION_TYPE + && TYPE_NAME (t) + && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) + { + /* Anonymous unions are objects, so they can have specifiers. */; + SET_ANON_UNION_TYPE_P (t); + } + + else if (ob_modifier) + { + if (ob_modifier == ridpointers[(int) RID_INLINE] + || ob_modifier == ridpointers[(int) RID_VIRTUAL]) + cp_error ("`%D' can only be specified for functions", ob_modifier); + else if (ob_modifier == ridpointers[(int) RID_FRIEND]) + cp_error ("`%D' can only be specified inside a class", ob_modifier); + else if (ob_modifier == ridpointers[(int) RID_EXPLICIT]) + cp_error ("`%D' can only be specified for constructors", + ob_modifier); + else + cp_error ("`%D' can only be specified for objects and functions", + ob_modifier); + } + + return t; +} + +/* Called when a declaration is seen that contains no names to declare. + If its type is a reference to a structure, union or enum inherited + from a containing scope, shadow that tag name for the current scope + with a forward reference. + If its type defines a new named structure or union + or defines an enum, it is valid but we need not do anything here. + Otherwise, it is an error. + + C++: may have to grok the declspecs to learn about static, + complain for anonymous unions. */ + +void +shadow_tag (declspecs) + tree declspecs; +{ + tree t = check_tag_decl (declspecs); + + if (t) + maybe_process_partial_specialization (t); + + /* This is where the variables in an anonymous union are + declared. An anonymous union declaration looks like: + union { ... } ; + because there is no declarator after the union, the parser + sends that declaration here. */ + if (t && ANON_UNION_TYPE_P (t)) + { + fixup_anonymous_union (t); + + if (TYPE_FIELDS (t)) + { + tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, + NULL_TREE); + finish_anon_union (decl); + } + } +} + +/* Decode a "typename", such as "int **", returning a ..._TYPE node. */ + +tree +groktypename (typename) + tree typename; +{ + if (TREE_CODE (typename) != TREE_LIST) + return typename; + return grokdeclarator (TREE_VALUE (typename), + TREE_PURPOSE (typename), + TYPENAME, 0, NULL_TREE); +} + +/* Decode a declarator in an ordinary declaration or data definition. + This is called as soon as the type information and variable name + have been parsed, before parsing the initializer if any. + Here we create the ..._DECL node, fill in its type, + and put it on the list of decls for the current context. + The ..._DECL node is returned as the value. + + Exception: for arrays where the length is not specified, + the type is left null, to be filled in by `cp_finish_decl'. + + Function definitions do not come here; they go to start_function + instead. However, external and forward declarations of functions + do go through here. Structure field declarations are done by + grokfield and not through here. */ + +/* Set this to zero to debug not using the temporary obstack + to parse initializers. */ +int debug_temp_inits = 1; + +tree +start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) + tree declarator, declspecs; + int initialized; + tree attributes, prefix_attributes; +{ + register tree decl; + register tree type, tem; + tree context; + extern int have_extern_spec; + extern int used_extern_spec; + tree attrlist; + +#if 0 + /* See code below that used this. */ + int init_written = initialized; +#endif + + /* This should only be done once on the top most decl. */ + if (have_extern_spec && !used_extern_spec) + { + declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), + declspecs); + used_extern_spec = 1; + } + + if (attributes || prefix_attributes) + attrlist = build_scratch_list (attributes, prefix_attributes); + else + attrlist = NULL_TREE; + + decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, + attrlist); + + if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE) + return NULL_TREE; + + type = TREE_TYPE (decl); + + if (type == error_mark_node) + return NULL_TREE; + + /* Don't lose if destructors must be executed at file-level. */ + if (! processing_template_decl && TREE_STATIC (decl) + && TYPE_NEEDS_DESTRUCTOR (complete_type (type)) + && !TREE_PERMANENT (decl)) + { + push_obstacks (&permanent_obstack, &permanent_obstack); + decl = copy_node (decl); + if (TREE_CODE (type) == ARRAY_TYPE) + { + tree itype = TYPE_DOMAIN (type); + if (itype && ! TREE_PERMANENT (itype)) + { + itype = build_index_type (copy_to_permanent (TYPE_MAX_VALUE (itype))); + type = build_cplus_array_type (TREE_TYPE (type), itype); + TREE_TYPE (decl) = type; + } + } + pop_obstacks (); + } + + context + = (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl)) + ? DECL_CLASS_CONTEXT (decl) + : DECL_CONTEXT (decl); + + if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL + && context != current_namespace && TREE_CODE (decl) == VAR_DECL) + { + /* When parsing the initializer, lookup should use the object's + namespace. */ + push_decl_namespace (context); + } + + /* We are only interested in class contexts, later. */ + if (context && TREE_CODE (context) == NAMESPACE_DECL) + context = NULL_TREE; + + if (initialized) + /* Is it valid for this decl to have an initializer at all? + If not, set INITIALIZED to zero, which will indirectly + tell `cp_finish_decl' to ignore the initializer once it is parsed. */ + switch (TREE_CODE (decl)) + { + case TYPE_DECL: + /* typedef foo = bar means give foo the same type as bar. + We haven't parsed bar yet, so `cp_finish_decl' will fix that up. + Any other case of an initialization in a TYPE_DECL is an error. */ + if (pedantic || list_length (declspecs) > 1) + { + cp_error ("typedef `%D' is initialized", decl); + initialized = 0; + } + break; + + case FUNCTION_DECL: + cp_error ("function `%#D' is initialized like a variable", decl); + initialized = 0; + break; + + default: + if (! processing_template_decl) + { + if (type != error_mark_node) + { + if (TYPE_SIZE (type) != NULL_TREE + && ! TREE_CONSTANT (TYPE_SIZE (type))) + { + cp_error + ("variable-sized object `%D' may not be initialized", + decl); + initialized = 0; + } + + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE) + { + cp_error + ("elements of array `%#D' have incomplete type", decl); + initialized = 0; + } + } + } + } + + if (initialized) + { + if (! toplevel_bindings_p () + && DECL_EXTERNAL (decl)) + cp_warning ("declaration of `%#D' has `extern' and is initialized", + decl); + DECL_EXTERNAL (decl) = 0; + if (toplevel_bindings_p ()) + TREE_STATIC (decl) = 1; + + /* Tell `pushdecl' this is an initialized decl + even though we don't yet have the initializer expression. + Also tell `cp_finish_decl' it may store the real initializer. */ + DECL_INITIAL (decl) = error_mark_node; + } + +#ifdef SET_DEFAULT_DECL_ATTRIBUTES + SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes); +#endif + + /* Set attributes here so if duplicate decl, will have proper attributes. */ + cplus_decl_attributes (decl, attributes, prefix_attributes); + + if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE) + { + push_nested_class (context, 2); + + if (TREE_CODE (decl) == VAR_DECL) + { + tree field = lookup_field (context, DECL_NAME (decl), 0, 0); + if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL) + cp_error ("`%#D' is not a static member of `%#T'", decl, context); + else + { + if (DECL_CONTEXT (field) != context) + { + cp_pedwarn ("ANSI C++ does not permit `%T::%D' to be defined as `%T::%D'", + DECL_CONTEXT (field), DECL_NAME (decl), + context, DECL_NAME (decl)); + DECL_CONTEXT (decl) = DECL_CONTEXT (field); + } + /* Static data member are tricky; an in-class initialization + still doesn't provide a definition, so the in-class + declaration will have DECL_EXTERNAL set, but will have an + initialization. Thus, duplicate_decls won't warn + about this situation, and so we check here. */ + if (DECL_INITIAL (decl) && DECL_INITIAL (field)) + cp_error ("duplicate initialization of %D", decl); + if (duplicate_decls (decl, field)) + decl = field; + } + } + else + { + tree field = check_classfn (context, decl); + if (field && duplicate_decls (decl, field)) + decl = field; + } + + /* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set. */ + DECL_IN_AGGR_P (decl) = 0; + if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) + || CLASSTYPE_USE_TEMPLATE (context)) + { + SET_DECL_TEMPLATE_SPECIALIZATION (decl); + /* [temp.expl.spec] An explicit specialization of a static data + member of a template is a definition if the declaration + includes an initializer; otherwise, it is a declaration. + + We check for processing_specialization so this only applies + to the new specialization syntax. */ + if (DECL_INITIAL (decl) == NULL_TREE && processing_specialization) + DECL_EXTERNAL (decl) = 1; + } + + if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl)) + cp_pedwarn ("declaration of `%#D' outside of class is not definition", + decl); + } + + /* Add this decl to the current binding level, but not if it + comes from another scope, e.g. a static member variable. + TEM may equal DECL or it may be a previous decl of the same name. */ + + if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE + /* Definitions of namespace members outside their namespace are + possible. */ + && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL) + || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ()) + || TREE_CODE (type) == LANG_TYPE + /* The declaration of template specializations does not affect + the functions available for overload resolution, so we do not + call pushdecl. */ + || (TREE_CODE (decl) == FUNCTION_DECL + && DECL_TEMPLATE_SPECIALIZATION (decl))) + tem = decl; + else + tem = pushdecl (decl); + + if (processing_template_decl) + { + if (! current_function_decl) + tem = push_template_decl (tem); + else if (minimal_parse_mode) + DECL_VINDEX (tem) + = build_min_nt (DECL_STMT, copy_to_permanent (declarator), + copy_to_permanent (declspecs), + NULL_TREE); + } + + +#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS) + /* Tell the back-end to use or not use .common as appropriate. If we say + -fconserve-space, we want this to save .data space, at the expense of + wrong semantics. If we say -fno-conserve-space, we want this to + produce errors about redefs; to do this we force variables into the + data segment. */ + DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem); +#endif + + if (! processing_template_decl) + start_decl_1 (tem); + + /* Corresponding pop_obstacks is done in `cp_finish_decl'. */ + push_obstacks_nochange (); + +#if 0 + /* We have no way of knowing whether the initializer will need to be + evaluated at run-time or not until we've parsed it, so let's just put + it in the permanent obstack. (jason) */ + if (init_written + && ! (TREE_CODE (tem) == PARM_DECL + || (TREE_READONLY (tem) + && (TREE_CODE (tem) == VAR_DECL + || TREE_CODE (tem) == FIELD_DECL)))) + { + /* When parsing and digesting the initializer, + use temporary storage. Do this even if we will ignore the value. */ + if (toplevel_bindings_p () && debug_temp_inits) + { + if (processing_template_decl + || TYPE_NEEDS_CONSTRUCTING (type) + || TREE_CODE (type) == REFERENCE_TYPE) + /* In this case, the initializer must lay down in permanent + storage, since it will be saved until `finish_file' is run. */ + ; + else + temporary_allocation (); + } + } +#endif + + return tem; +} + +void +start_decl_1 (decl) + tree decl; +{ + tree type = TREE_TYPE (decl); + int initialized = (DECL_INITIAL (decl) != NULL_TREE); + + if (type == error_mark_node) + return; + + /* If this type of object needs a cleanup, and control may + jump past it, make a new binding level so that it is cleaned + up only when it is initialized first. */ + if (TYPE_NEEDS_DESTRUCTOR (type) + && current_binding_level->more_cleanups_ok == 0) + pushlevel_temporary (1); + + if (initialized) + /* Is it valid for this decl to have an initializer at all? + If not, set INITIALIZED to zero, which will indirectly + tell `cp_finish_decl' to ignore the initializer once it is parsed. */ + { + /* Don't allow initializations for incomplete types except for + arrays which might be completed by the initialization. */ + if (TYPE_SIZE (complete_type (type)) != NULL_TREE) + ; /* A complete type is ok. */ + else if (TREE_CODE (type) != ARRAY_TYPE) + { + cp_error ("variable `%#D' has initializer but incomplete type", + decl); + initialized = 0; + type = TREE_TYPE (decl) = error_mark_node; + } + else if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE) + { + if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) + cp_error ("elements of array `%#D' have incomplete type", decl); + /* else we already gave an error in start_decl. */ + initialized = 0; + } + } + + if (!initialized + && TREE_CODE (decl) != TYPE_DECL + && TREE_CODE (decl) != TEMPLATE_DECL + && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl)) + { + if ((! processing_template_decl || ! uses_template_parms (type)) + && TYPE_SIZE (complete_type (type)) == NULL_TREE) + { + cp_error ("aggregate `%#D' has incomplete type and cannot be initialized", + decl); + /* Change the type so that assemble_variable will give + DECL an rtl we can live with: (mem (const_int 0)). */ + type = TREE_TYPE (decl) = error_mark_node; + } + else + { + /* If any base type in the hierarchy of TYPE needs a constructor, + then we set initialized to 1. This way any nodes which are + created for the purposes of initializing this aggregate + will live as long as it does. This is necessary for global + aggregates which do not have their initializers processed until + the end of the file. */ + initialized = TYPE_NEEDS_CONSTRUCTING (type); + } + } + +#if 0 + /* We don't do this yet for GNU C++. */ + /* For a local variable, define the RTL now. */ + if (! toplevel_bindings_p () + /* But not if this is a duplicate decl + and we preserved the rtl from the previous one + (which may or may not happen). */ + && DECL_RTL (tem) == NULL_RTX) + { + if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE) + expand_decl (tem); + else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE + && DECL_INITIAL (tem) != NULL_TREE) + expand_decl (tem); + } +#endif + + if (! initialized) + DECL_INITIAL (decl) = NULL_TREE; +} + +/* Handle initialization of references. + These three arguments are from `cp_finish_decl', and have the + same meaning here that they do there. + + Quotes on semantics can be found in ARM 8.4.3. */ + +static void +grok_reference_init (decl, type, init) + tree decl, type, init; +{ + tree tmp; + + if (init == NULL_TREE) + { + if ((DECL_LANG_SPECIFIC (decl) == 0 + || DECL_IN_AGGR_P (decl) == 0) + && ! DECL_THIS_EXTERN (decl)) + { + cp_error ("`%D' declared as reference but not initialized", decl); + if (TREE_CODE (decl) == VAR_DECL) + SET_DECL_REFERENCE_SLOT (decl, error_mark_node); + } + return; + } + + if (init == error_mark_node) + return; + + if (TREE_CODE (type) == REFERENCE_TYPE + && TREE_CODE (init) == CONSTRUCTOR) + { + cp_error ("ANSI C++ forbids use of initializer list to initialize reference `%D'", decl); + return; + } + + if (TREE_CODE (init) == TREE_LIST) + init = build_compound_expr (init); + + if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE) + init = convert_from_reference (init); + + if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE + && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) + { + /* Note: default conversion is only called in very special cases. */ + init = default_conversion (init); + } + + tmp = convert_to_reference + (type, init, CONV_IMPLICIT, + LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl); + + if (tmp == error_mark_node) + goto fail; + else if (tmp != NULL_TREE) + { + init = tmp; + DECL_INITIAL (decl) = save_expr (init); + } + else + { + cp_error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init)); + goto fail; + } + + /* ?? Can this be optimized in some cases to + hand back the DECL_INITIAL slot?? */ + if (TYPE_SIZE (TREE_TYPE (type))) + { + init = convert_from_reference (decl); + if (TREE_PERMANENT (decl)) + init = copy_to_permanent (init); + SET_DECL_REFERENCE_SLOT (decl, init); + } + + if (TREE_STATIC (decl) && ! TREE_CONSTANT (DECL_INITIAL (decl))) + { + expand_static_init (decl, DECL_INITIAL (decl)); + DECL_INITIAL (decl) = NULL_TREE; + } + return; + + fail: + if (TREE_CODE (decl) == VAR_DECL) + SET_DECL_REFERENCE_SLOT (decl, error_mark_node); + return; +} + +/* Fill in DECL_INITIAL with some magical value to prevent expand_decl from + mucking with forces it does not comprehend (i.e. initialization with a + constructor). If we are at global scope and won't go into COMMON, fill + it in with a dummy CONSTRUCTOR to force the variable into .data; + otherwise we can use error_mark_node. */ + +static tree +obscure_complex_init (decl, init) + tree decl, init; +{ + if (! flag_no_inline && TREE_STATIC (decl)) + { + if (extract_init (decl, init)) + return NULL_TREE; + } + +#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS) + if (toplevel_bindings_p () && ! DECL_COMMON (decl)) + DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, + NULL_TREE); + else +#endif + DECL_INITIAL (decl) = error_mark_node; + + return init; +} + +/* Issue an error message if DECL is an uninitialized const variable. */ + +static void +check_for_uninitialized_const_var (decl) + tree decl; +{ + tree type = TREE_TYPE (decl); + + /* ``Unless explicitly declared extern, a const object does not have + external linkage and must be initialized. ($8.4; $12.1)'' ARM + 7.1.6 */ + if (TREE_CODE (decl) == VAR_DECL + && TREE_CODE (type) != REFERENCE_TYPE + && CP_TYPE_CONST_P (type) + && !TYPE_NEEDS_CONSTRUCTING (type) + && !DECL_INITIAL (decl)) + cp_error ("uninitialized const `%D'", decl); +} + +/* Finish processing of a declaration; + install its line number and initial value. + If the length of an array type is not known before, + it must be determined now, from the initial value, or it is an error. + + Call `pop_obstacks' iff NEED_POP is nonzero. + + For C++, `cp_finish_decl' must be fairly evasive: it must keep initializers + for aggregates that have constructors alive on the permanent obstack, + so that the global initializing functions can be written at the end. + + INIT0 holds the value of an initializer that should be allowed to escape + the normal rules. + + FLAGS is LOOKUP_ONLYCONVERTING is the = init syntax was used, else 0 + if the (init) syntax was used. + + For functions that take default parameters, DECL points to its + "maximal" instantiation. `cp_finish_decl' must then also declared its + subsequently lower and lower forms of instantiation, checking for + ambiguity as it goes. This can be sped up later. */ + +void +cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) + tree decl, init; + tree asmspec_tree; + int need_pop; + int flags; +{ + register tree type; + tree cleanup = NULL_TREE, ttype = NULL_TREE; + int was_incomplete; + int temporary = allocation_temporary_p (); + char *asmspec = NULL; + int was_readonly = 0; + int already_used = 0; + tree core_type; + + /* If this is 0, then we did not change obstacks. */ + if (! decl) + { + if (init) + error ("assignment (not initialization) in declaration"); + return; + } + + /* If a name was specified, get the string. */ + if (asmspec_tree) + asmspec = TREE_STRING_POINTER (asmspec_tree); + + if (init && TREE_CODE (init) == NAMESPACE_DECL) + { + cp_error ("Cannot initialize `%D' to namespace `%D'", + decl, init); + init = NULL_TREE; + } + + if (current_class_type + && DECL_REAL_CONTEXT (decl) == current_class_type + && TYPE_BEING_DEFINED (current_class_type) + && (DECL_INITIAL (decl) || init)) + DECL_DEFINED_IN_CLASS_P (decl) = 1; + + if (TREE_CODE (decl) == VAR_DECL + && DECL_CONTEXT (decl) + && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL + && DECL_CONTEXT (decl) != current_namespace + && init) + { + /* Leave the namespace of the object. */ + pop_decl_namespace (); + } + + /* If the type of the thing we are declaring either has + a constructor, or has a virtual function table pointer, + AND its initialization was accepted by `start_decl', + then we stayed on the permanent obstack through the + declaration, otherwise, changed obstacks as GCC would. */ + + type = TREE_TYPE (decl); + + if (type == error_mark_node) + { + if (toplevel_bindings_p () && temporary) + end_temporary_allocation (); + + return; + } + + if (TYPE_HAS_MUTABLE_P (type)) + TREE_READONLY (decl) = 0; + + if (processing_template_decl) + { + if (init && DECL_INITIAL (decl)) + DECL_INITIAL (decl) = init; + if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl)) + { + tree stmt = DECL_VINDEX (decl); + /* If the decl is declaring a member of a local class (in a + template function), the DECL_VINDEX will either be NULL, + or it will be an actual virtual function index, not a + DECL_STMT. */ + if (stmt != NULL_TREE && TREE_CODE (stmt) == DECL_STMT) + { + DECL_VINDEX (decl) = NULL_TREE; + TREE_OPERAND (stmt, 2) = copy_to_permanent (init); + add_tree (stmt); + } + } + + goto finish_end0; + } + /* Take care of TYPE_DECLs up front. */ + if (TREE_CODE (decl) == TYPE_DECL) + { + if (init && DECL_INITIAL (decl)) + { + /* typedef foo = bar; store the type of bar as the type of foo. */ + TREE_TYPE (decl) = type = TREE_TYPE (init); + DECL_INITIAL (decl) = init = NULL_TREE; + } + if (type != error_mark_node + && IS_AGGR_TYPE (type) && DECL_NAME (decl)) + { + if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type) + cp_warning ("shadowing previous type declaration of `%#D'", decl); + set_identifier_type_value (DECL_NAME (decl), type); + CLASSTYPE_GOT_SEMICOLON (type) = 1; + } + GNU_xref_decl (current_function_decl, decl); + + /* If we have installed this as the canonical typedef for this + type, and that type has not been defined yet, delay emitting + the debug information for it, as we will emit it later. */ + if (TYPE_MAIN_DECL (TREE_TYPE (decl)) == decl + && TYPE_SIZE (TREE_TYPE (decl)) == NULL_TREE) + TYPE_DECL_SUPPRESS_DEBUG (decl) = 1; + + rest_of_decl_compilation (decl, NULL_PTR, + DECL_CONTEXT (decl) == NULL_TREE, at_eof); + goto finish_end; + } + if (TREE_CODE (decl) != FUNCTION_DECL) + { + ttype = target_type (type); + } + + if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl) + && TYPE_NEEDS_CONSTRUCTING (type)) + { + + /* Currently, GNU C++ puts constants in text space, making them + impossible to initialize. In the future, one would hope for + an operating system which understood the difference between + initialization and the running of a program. */ + was_readonly = 1; + TREE_READONLY (decl) = 0; + } + + if (TREE_CODE (decl) == FIELD_DECL) + { + if (init && init != error_mark_node) + my_friendly_assert (TREE_PERMANENT (init), 147); + + if (asmspec) + { + /* This must override the asm specifier which was placed + by grokclassfn. Lay this out fresh. */ + DECL_RTL (TREE_TYPE (decl)) = NULL_RTX; + DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec); + make_decl_rtl (decl, asmspec, 0); + } + } + /* If `start_decl' didn't like having an initialization, ignore it now. */ + else if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE) + init = NULL_TREE; + else if (DECL_EXTERNAL (decl)) + ; + else if (TREE_CODE (type) == REFERENCE_TYPE + || (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE_REFERENCE (type))) + { + if (TREE_STATIC (decl)) + make_decl_rtl (decl, NULL_PTR, + toplevel_bindings_p () + || pseudo_global_level_p ()); + grok_reference_init (decl, type, init); + init = NULL_TREE; + } + + GNU_xref_decl (current_function_decl, decl); + + core_type = type; + while (TREE_CODE (core_type) == ARRAY_TYPE) + core_type = TREE_TYPE (core_type); + + if (TREE_CODE (decl) == FIELD_DECL) + ; + else if (TREE_CODE (decl) == CONST_DECL) + { + my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148); + + DECL_INITIAL (decl) = init; + + /* This will keep us from needing to worry about our obstacks. */ + my_friendly_assert (init != NULL_TREE, 149); + init = NULL_TREE; + } + else if (init) + { + if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type)) + { + if (TREE_CODE (type) == ARRAY_TYPE) + init = digest_init (type, init, (tree *) 0); + else if (TREE_CODE (init) == CONSTRUCTOR + && TREE_HAS_CONSTRUCTOR (init)) + { + if (TYPE_NON_AGGREGATE_CLASS (type)) + { + cp_error ("`%D' must be initialized by constructor, not by `{...}'", + decl); + init = error_mark_node; + } + else + goto dont_use_constructor; + } + } + else + { + dont_use_constructor: + if (TREE_CODE (init) != TREE_VEC) + init = store_init_value (decl, init); + } + + if (init) + /* We must hide the initializer so that expand_decl + won't try to do something it does not understand. */ + init = obscure_complex_init (decl, init); + } + else if (DECL_EXTERNAL (decl)) + ; + else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't' + && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type))) + { + if (! TYPE_NEEDS_CONSTRUCTING (core_type)) + { + if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)) + cp_error ("structure `%D' with uninitialized const members", decl); + if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)) + cp_error ("structure `%D' with uninitialized reference members", + decl); + } + + check_for_uninitialized_const_var (decl); + + if (TYPE_SIZE (type) != NULL_TREE + && TYPE_NEEDS_CONSTRUCTING (type)) + init = obscure_complex_init (decl, NULL_TREE); + + } + else + check_for_uninitialized_const_var (decl); + + /* For top-level declaration, the initial value was read in + the temporary obstack. MAXINDEX, rtl, etc. to be made below + must go in the permanent obstack; but don't discard the + temporary data yet. */ + + if (toplevel_bindings_p () && temporary) + end_temporary_allocation (); + + /* Deduce size of array from initialization, if not already known. */ + + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_DOMAIN (type) == NULL_TREE + && TREE_CODE (decl) != TYPE_DECL) + { + int do_default + = (TREE_STATIC (decl) + /* Even if pedantic, an external linkage array + may have incomplete type at first. */ + ? pedantic && ! DECL_EXTERNAL (decl) + : !DECL_EXTERNAL (decl)); + tree initializer = init ? init : DECL_INITIAL (decl); + int failure = complete_array_type (type, initializer, do_default); + + if (failure == 1) + cp_error ("initializer fails to determine size of `%D'", decl); + + if (failure == 2) + { + if (do_default) + cp_error ("array size missing in `%D'", decl); + /* If a `static' var's size isn't known, make it extern as + well as static, so it does not get allocated. If it's not + `static', then don't mark it extern; finish_incomplete_decl + will give it a default size and it will get allocated. */ + else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl)) + DECL_EXTERNAL (decl) = 1; + } + + if (pedantic && TYPE_DOMAIN (type) != NULL_TREE + && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), + integer_zero_node)) + cp_error ("zero-size array `%D'", decl); + + layout_decl (decl, 0); + } + + if (TREE_CODE (decl) == VAR_DECL) + { + if (DECL_SIZE (decl) == NULL_TREE + && TYPE_SIZE (complete_type (TREE_TYPE (decl))) != NULL_TREE) + layout_decl (decl, 0); + + if (TREE_STATIC (decl) && DECL_SIZE (decl) == NULL_TREE) + { + /* A static variable with an incomplete type: + that is an error if it is initialized. + Otherwise, let it through, but if it is not `extern' + then it may cause an error message later. */ + if (DECL_INITIAL (decl) != NULL_TREE) + cp_error ("storage size of `%D' isn't known", decl); + init = NULL_TREE; + } + else if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE) + { + /* An automatic variable with an incomplete type: that is an error. + Don't talk about array types here, since we took care of that + message in grokdeclarator. */ + cp_error ("storage size of `%D' isn't known", decl); + TREE_TYPE (decl) = error_mark_node; + } + else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype)) + /* Let debugger know it should output info for this type. */ + note_debug_info_needed (ttype); + + if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl)) + note_debug_info_needed (DECL_CONTEXT (decl)); + + if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) + && DECL_SIZE (decl) != NULL_TREE + && ! TREE_CONSTANT (DECL_SIZE (decl))) + { + if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST) + constant_expression_warning (DECL_SIZE (decl)); + else + cp_error ("storage size of `%D' isn't constant", decl); + } + + if (! DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type) + /* Cleanups for static variables are handled by `finish_file'. */ + && ! TREE_STATIC (decl)) + { + int yes = suspend_momentary (); + cleanup = maybe_build_cleanup (decl); + resume_momentary (yes); + } + } + /* PARM_DECLs get cleanups, too. */ + else if (TREE_CODE (decl) == PARM_DECL && TYPE_NEEDS_DESTRUCTOR (type)) + { + if (temporary) + end_temporary_allocation (); + cleanup = maybe_build_cleanup (decl); + if (temporary) + resume_temporary_allocation (); + } + + /* Output the assembler code and/or RTL code for variables and functions, + unless the type is an undefined structure or union. + If not, it will get done when the type is completed. */ + + was_incomplete = (DECL_SIZE (decl) == NULL_TREE); + + if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == RESULT_DECL) + { + /* ??? FIXME: What about nested classes? */ + int toplev = toplevel_bindings_p () || pseudo_global_level_p (); + int was_temp + = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type) + && allocation_temporary_p ()); + + if (was_temp) + end_temporary_allocation (); + + /* Static data in a function with comdat linkage also has comdat + linkage. */ + if (TREE_CODE (decl) == VAR_DECL + && TREE_STATIC (decl) + /* Don't mess with __FUNCTION__. */ + && ! TREE_ASM_WRITTEN (decl) + && current_function_decl + && DECL_CONTEXT (decl) == current_function_decl + && (DECL_THIS_INLINE (current_function_decl) + || DECL_TEMPLATE_INSTANTIATION (current_function_decl)) + && TREE_PUBLIC (current_function_decl)) + { + /* Rather than try to get this right with inlining, we suppress + inlining of such functions. */ + current_function_cannot_inline + = "function with static variable cannot be inline"; + + /* If flag_weak, we don't need to mess with this, as we can just + make the function weak, and let it refer to its unique local + copy. This works because we don't allow the function to be + inlined. */ + if (! flag_weak) + { + if (DECL_INTERFACE_KNOWN (current_function_decl)) + { + TREE_PUBLIC (decl) = 1; + DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl); + } + else if (DECL_INITIAL (decl) == NULL_TREE + || DECL_INITIAL (decl) == error_mark_node) + { + TREE_PUBLIC (decl) = 1; + DECL_COMMON (decl) = 1; + } + /* else we lose. We can only do this if we can use common, + which we can't if it has been initialized. */ + + if (TREE_PUBLIC (decl)) + DECL_ASSEMBLER_NAME (decl) + = build_static_name (current_function_decl, DECL_NAME (decl)); + else if (! DECL_ARTIFICIAL (decl)) + { + cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl); + cp_warning_at (" you can work around this by removing the initializer", decl); + } + } + } + + else if (TREE_CODE (decl) == VAR_DECL + && DECL_LANG_SPECIFIC (decl) + && DECL_COMDAT (decl)) + /* Set it up again; we might have set DECL_INITIAL since the + last time. */ + comdat_linkage (decl); + + if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl)) + make_decl_rtl (decl, NULL_PTR, toplev); + else if (TREE_CODE (decl) == VAR_DECL + && TREE_READONLY (decl) + && DECL_INITIAL (decl) != NULL_TREE + && DECL_INITIAL (decl) != error_mark_node + && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))) + { + DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl)); + + if (asmspec) + DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec); + + if (! toplev + && TREE_STATIC (decl) + && ! TREE_SIDE_EFFECTS (decl) + && ! TREE_PUBLIC (decl) + && ! DECL_EXTERNAL (decl) + && ! TYPE_NEEDS_DESTRUCTOR (type) + && DECL_MODE (decl) != BLKmode) + { + /* If this variable is really a constant, then fill its DECL_RTL + slot with something which won't take up storage. + If something later should take its address, we can always give + it legitimate RTL at that time. */ + DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl)); + store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0); + TREE_ASM_WRITTEN (decl) = 1; + } + else if (toplev && ! TREE_PUBLIC (decl)) + { + /* If this is a static const, change its apparent linkage + if it belongs to a #pragma interface. */ + if (!interface_unknown) + { + TREE_PUBLIC (decl) = 1; + DECL_EXTERNAL (decl) = interface_only; + } + make_decl_rtl (decl, asmspec, toplev); + } + else + rest_of_decl_compilation (decl, asmspec, toplev, at_eof); + } + else if (TREE_CODE (decl) == VAR_DECL + && DECL_LANG_SPECIFIC (decl) + && DECL_IN_AGGR_P (decl)) + { + if (TREE_STATIC (decl)) + { + if (init == NULL_TREE +#ifdef DEFAULT_STATIC_DEFS + /* If this code is dead, then users must + explicitly declare static member variables + outside the class def'n as well. */ + && TYPE_NEEDS_CONSTRUCTING (type) +#endif + ) + { + DECL_EXTERNAL (decl) = 1; + make_decl_rtl (decl, asmspec, 1); + } + else + rest_of_decl_compilation (decl, asmspec, toplev, at_eof); + } + else + /* Just a constant field. Should not need any rtl. */ + goto finish_end0; + } + else + rest_of_decl_compilation (decl, asmspec, toplev, at_eof); + + if (was_temp) + resume_temporary_allocation (); + + if (type != error_mark_node + && TYPE_LANG_SPECIFIC (core_type) + && CLASSTYPE_ABSTRACT_VIRTUALS (core_type)) + abstract_virtuals_error (decl, core_type); + else if ((TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) + && TYPE_LANG_SPECIFIC (TREE_TYPE (type)) + && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (type))) + abstract_virtuals_error (decl, TREE_TYPE (type)); + + if (TYPE_LANG_SPECIFIC (core_type) && IS_SIGNATURE (core_type)) + signature_error (decl, core_type); + else if ((TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) + && TYPE_LANG_SPECIFIC (TREE_TYPE (type)) + && IS_SIGNATURE (TREE_TYPE (type))) + signature_error (decl, TREE_TYPE (type)); + + if (TREE_CODE (decl) == FUNCTION_DECL) + ; + else if (DECL_EXTERNAL (decl) + && ! (DECL_LANG_SPECIFIC (decl) + && DECL_NOT_REALLY_EXTERN (decl))) + { + if (init) + DECL_INITIAL (decl) = init; + } + else if (TREE_STATIC (decl) && type != error_mark_node) + { + /* Cleanups for static variables are handled by `finish_file'. */ + if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE + || TYPE_NEEDS_DESTRUCTOR (type)) + expand_static_init (decl, init); + } + else if (! toplev) + { + /* This is a declared decl which must live until the + end of the binding contour. It may need a cleanup. */ + + /* Recompute the RTL of a local array now + if it used to be an incomplete type. */ + if (was_incomplete && ! TREE_STATIC (decl)) + { + /* If we used it already as memory, it must stay in memory. */ + TREE_ADDRESSABLE (decl) = TREE_USED (decl); + /* If it's still incomplete now, no init will save it. */ + if (DECL_SIZE (decl) == NULL_TREE) + DECL_INITIAL (decl) = NULL_TREE; + expand_decl (decl); + } + else if (! TREE_ASM_WRITTEN (decl) + && (TYPE_SIZE (type) != NULL_TREE + || TREE_CODE (type) == ARRAY_TYPE)) + { + /* Do this here, because we did not expand this decl's + rtl in start_decl. */ + if (DECL_RTL (decl) == NULL_RTX) + expand_decl (decl); + else if (cleanup) + { + /* XXX: Why don't we use decl here? */ + /* Ans: Because it was already expanded? */ + if (! expand_decl_cleanup (NULL_TREE, cleanup)) + cp_error ("parser lost in parsing declaration of `%D'", + decl); + /* Cleanup used up here. */ + cleanup = NULL_TREE; + } + } + + if (current_binding_level->is_for_scope) + { + struct binding_level *outer + = current_binding_level->level_chain; + + /* Check to see if the same name is already bound at + the outer level, either because it was directly declared, + or because a dead for-decl got preserved. In either case, + the code would not have been valid under the ARM + scope rules, so clear is_for_scope for the + current_binding_level. + + Otherwise, we need to preserve the temp slot for decl + to last into the outer binding level. */ + + tree outer_binding + = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl))); + + if (outer_binding && BINDING_LEVEL (outer_binding) == outer + && (TREE_CODE (BINDING_VALUE (outer_binding)) + == VAR_DECL) + && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding))) + { + BINDING_VALUE (outer_binding) + = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding)); + current_binding_level->is_for_scope = 0; + } + else if (DECL_IN_MEMORY_P (decl)) + preserve_temp_slots (DECL_RTL (decl)); + } + + expand_start_target_temps (); + + if (DECL_SIZE (decl) && type != error_mark_node) + { + /* Compute and store the initial value. */ + expand_decl_init (decl); + already_used = TREE_USED (decl) || TREE_USED (type); + + if (init || TYPE_NEEDS_CONSTRUCTING (type)) + { + emit_line_note (DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + expand_aggr_init (decl, init, flags); + } + + /* Set this to 0 so we can tell whether an aggregate which + was initialized was ever used. Don't do this if it has a + destructor, so we don't complain about the 'resource + allocation is initialization' idiom. */ + /* Now set attribute((unused)) on types so decls of + that type will be marked used. (see TREE_USED, above.) + This avoids the warning problems this particular code + tried to work around. */ + + if (TYPE_NEEDS_CONSTRUCTING (type) + && ! already_used + && cleanup == NULL_TREE + && DECL_NAME (decl)) + TREE_USED (decl) = 0; + + if (already_used) + TREE_USED (decl) = 1; + } + + /* Cleanup any temporaries needed for the initial value. */ + expand_end_target_temps (); + + if (DECL_SIZE (decl) && type != error_mark_node) + { + /* Store the cleanup, if there was one. */ + if (cleanup) + { + if (! expand_decl_cleanup (decl, cleanup)) + cp_error ("parser lost in parsing declaration of `%D'", + decl); + } + } + } + finish_end0: + + /* Undo call to `pushclass' that was done in `start_decl' + due to initialization of qualified member variable. + I.e., Foo::x = 10; */ + { + tree context = DECL_REAL_CONTEXT (decl); + if (context + && TREE_CODE_CLASS (TREE_CODE (context)) == 't' + && (TREE_CODE (decl) == VAR_DECL + /* We also have a pushclass done that we need to undo here + if we're at top level and declare a method. */ + || TREE_CODE (decl) == FUNCTION_DECL) + /* If size hasn't been set, we're still defining it, + and therefore inside the class body; don't pop + the binding level.. */ + && TYPE_SIZE (context) != NULL_TREE + && context == current_class_type) + pop_nested_class (); + } + } + + finish_end: + + /* If requested, warn about definitions of large data objects. */ + + if (warn_larger_than + && ! processing_template_decl + && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) + && !DECL_EXTERNAL (decl)) + { + register tree decl_size = DECL_SIZE (decl); + + if (decl_size && TREE_CODE (decl_size) == INTEGER_CST) + { + unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT; + + if (units > larger_than_size) + warning_with_decl (decl, "size of `%s' is %u bytes", units); + } + } + + if (need_pop) + { + /* Resume permanent allocation, if not within a function. */ + /* The corresponding push_obstacks_nochange is in start_decl, + start_method, groktypename, and in grokfield. */ + pop_obstacks (); + } + + if (was_readonly) + TREE_READONLY (decl) = 1; +} + +/* This is here for a midend callback from c-common.c */ + +void +finish_decl (decl, init, asmspec_tree) + tree decl, init; + tree asmspec_tree; +{ + cp_finish_decl (decl, init, asmspec_tree, 1, 0); +} + +void +expand_static_init (decl, init) + tree decl; + tree init; +{ + tree oldstatic = value_member (decl, static_aggregates); + + if (oldstatic) + { + if (TREE_PURPOSE (oldstatic) && init != NULL_TREE) + cp_error ("multiple initializations given for `%D'", decl); + } + else if (! toplevel_bindings_p ()) + { + /* Emit code to perform this initialization but once. */ + tree temp; + + /* Remember this information until end of file. */ + push_obstacks (&permanent_obstack, &permanent_obstack); + + /* Emit code to perform this initialization but once. This code + looks like: + + static int temp = 0; + if (!temp) { + // Do initialization. + temp = 1; + // Register variable for destruction at end of program. + } + + Note that the `temp' variable is only set to 1 *after* the + initialization is complete. This ensures that an exception, + thrown during the construction, will cause the variable to + reinitialized when we pass through this code again, as per: + + [stmt.dcl] + + If the initialization exits by throwing an exception, the + initialization is not complete, so it will be tried again + the next time control enters the declaration. + + In theory, this process should be thread-safe, too; multiple + threads should not be able to initialize the variable more + than once. We don't yet attempt to ensure thread-safety. */ + temp = get_temp_name (integer_type_node, 1); + rest_of_decl_compilation (temp, NULL_PTR, 0, 0); + + /* Begin the conditional initialization. */ + expand_start_cond (build_binary_op (EQ_EXPR, temp, + integer_zero_node), 0); + expand_start_target_temps (); + + /* Do the initialization itself. */ + if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)) + || (init && TREE_CODE (init) == TREE_LIST)) + { + expand_aggr_init (decl, init, 0); + do_pending_stack_adjust (); + } + else if (init) + expand_assignment (decl, init, 0, 0); + + /* Set TEMP to 1. */ + expand_assignment (temp, integer_one_node, 0, 0); + + /* Cleanup any temporaries needed for the initial value. If + destroying one of the temporaries causes an exception to be + thrown, then the object itself has still been fully + constructed. */ + expand_end_target_temps (); + + /* Use atexit to register a function for destroying this static + variable. */ + if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl))) + { + tree cleanup, fcall; + static tree Atexit = 0; + int saved_flag_access_control; + + if (Atexit == 0) + { + tree atexit_fndecl, PFV, pfvlist; + /* Remember this information until end of file. */ + push_obstacks (&permanent_obstack, &permanent_obstack); + PFV = build_pointer_type (build_function_type + (void_type_node, void_list_node)); + + pfvlist = tree_cons (NULL_TREE, PFV, void_list_node); + + push_lang_context (lang_name_c); + atexit_fndecl + = builtin_function ("atexit", + build_function_type (void_type_node, + pfvlist), + NOT_BUILT_IN, NULL_PTR); + mark_used (atexit_fndecl); + Atexit = default_conversion (atexit_fndecl); + pop_lang_context (); + pop_obstacks (); + } + + /* Call build_cleanup before we enter the anonymous function + so that any access checks will be done relative to the + current scope, rather than the scope of the anonymous + function. */ + build_cleanup (decl); + + /* Now start the function. */ + cleanup = start_anon_func (); + + /* Now, recompute the cleanup. It may contain SAVE_EXPRs + that refer to the original function, rather than the + anonymous one. That will make the back-end think that + nested functions are in use, which causes confusion. */ + saved_flag_access_control = flag_access_control; + flag_access_control = 0; + fcall = build_cleanup (decl); + flag_access_control = saved_flag_access_control; + + /* Finish off the function. */ + expand_expr_stmt (fcall); + end_anon_func (); + + /* Call atexit with the cleanup function. */ + mark_addressable (cleanup); + cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); + fcall = build_function_call (Atexit, + expr_tree_cons (NULL_TREE, + cleanup, + NULL_TREE)); + expand_expr_stmt (fcall); + } + + expand_end_cond (); + /* Resume old (possibly temporary) allocation. */ + pop_obstacks (); + } + else + { + /* This code takes into account memory allocation policy of + `start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING does not + hold for this object, then we must make permanent the storage + currently in the temporary obstack. */ + if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) + preserve_initializer (); + static_aggregates = perm_tree_cons (init, decl, static_aggregates); + } +} + +/* Make TYPE a complete type based on INITIAL_VALUE. + Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered, + 2 if there was no information (in which case assume 0 if DO_DEFAULT). */ + +int +complete_array_type (type, initial_value, do_default) + tree type, initial_value; + int do_default; +{ + register tree maxindex = NULL_TREE; + int value = 0; + + /* Allocate on the same obstack as TYPE. */ + push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type)); + + if (initial_value) + { + /* Note MAXINDEX is really the maximum index, + one less than the size. */ + if (TREE_CODE (initial_value) == STRING_CST) + { + int eltsize + = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); + maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value) + / eltsize) - 1, 0); + } + else if (TREE_CODE (initial_value) == CONSTRUCTOR) + { + tree elts = CONSTRUCTOR_ELTS (initial_value); + maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node); + for (; elts; elts = TREE_CHAIN (elts)) + { + if (TREE_PURPOSE (elts)) + maxindex = TREE_PURPOSE (elts); + else + maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node); + } + maxindex = copy_node (maxindex); + } + else + { + /* Make an error message unless that happened already. */ + if (initial_value != error_mark_node) + value = 1; + else + initial_value = NULL_TREE; + + /* Prevent further error messages. */ + maxindex = build_int_2 (0, 0); + } + } + + if (!maxindex) + { + if (do_default) + maxindex = build_int_2 (0, 0); + value = 2; + } + + if (maxindex) + { + tree itype; + tree domain; + + domain = build_index_type (maxindex); + TYPE_DOMAIN (type) = domain; + + if (! TREE_TYPE (maxindex)) + TREE_TYPE (maxindex) = domain; + if (initial_value) + itype = TREE_TYPE (initial_value); + else + itype = NULL; + if (itype && !TYPE_DOMAIN (itype)) + TYPE_DOMAIN (itype) = domain; + /* The type of the main variant should never be used for arrays + of different sizes. It should only ever be completed with the + size of the array. */ + if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type))) + TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain; + } + + pop_obstacks(); + + /* Lay out the type now that we can get the real answer. */ + + layout_type (type); + + return value; +} + +/* Return zero if something is declared to be a member of type + CTYPE when in the context of CUR_TYPE. STRING is the error + message to print in that case. Otherwise, quietly return 1. */ + +static int +member_function_or_else (ctype, cur_type, string) + tree ctype, cur_type; + const char *string; +{ + if (ctype && ctype != cur_type) + { + error (string, TYPE_NAME_STRING (ctype)); + return 0; + } + return 1; +} + +/* Subroutine of `grokdeclarator'. */ + +/* Generate errors possibly applicable for a given set of specifiers. + This is for ARM $7.1.2. */ + +static void +bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises) + tree object; + const char *type; + int virtualp, quals, friendp, raises, inlinep; +{ + if (virtualp) + cp_error ("`%D' declared as a `virtual' %s", object, type); + if (inlinep) + cp_error ("`%D' declared as an `inline' %s", object, type); + if (quals) + cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration", + object, type); + if (friendp) + cp_error_at ("invalid friend declaration", object); + if (raises) + cp_error_at ("invalid exception specifications", object); +} + +/* CTYPE is class type, or null if non-class. + TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE + or METHOD_TYPE. + DECLARATOR is the function's name. + VIRTUALP is truthvalue of whether the function is virtual or not. + FLAGS are to be passed through to `grokclassfn'. + QUALS are qualifiers indicating whether the function is `const' + or `volatile'. + RAISES is a list of exceptions that this function can raise. + CHECK is 1 if we must find this method in CTYPE, 0 if we should + not look, and -1 if we should not call `grokclassfn' at all. + + Returns `NULL_TREE' if something goes wrong, after issuing + applicable error messages. */ + +static tree +grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, + raises, check, friendp, publicp, inlinep, funcdef_flag, + template_count, in_namespace) + tree ctype, type; + tree declarator; + tree orig_declarator; + int virtualp; + enum overload_flags flags; + tree quals, raises; + int check, friendp, publicp, inlinep, funcdef_flag, template_count; + tree in_namespace; +{ + tree cname, decl; + int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE; + int has_default_arg = 0; + tree t; + + if (ctype) + cname = TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL + ? TYPE_IDENTIFIER (ctype) : TYPE_NAME (ctype); + else + cname = NULL_TREE; + + if (raises) + { + type = build_exception_variant (type, raises); + } + + decl = build_lang_decl (FUNCTION_DECL, declarator, type); + /* Propagate volatile out from type to decl. */ + if (TYPE_VOLATILE (type)) + TREE_THIS_VOLATILE (decl) = 1; + + /* If this decl has namespace scope, set that up. */ + if (in_namespace) + set_decl_namespace (decl, in_namespace, friendp); + else if (publicp && ! ctype) + DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); + + /* `main' and builtins have implicit 'C' linkage. */ + if ((MAIN_NAME_P (declarator) + || (IDENTIFIER_LENGTH (declarator) > 10 + && IDENTIFIER_POINTER (declarator)[0] == '_' + && IDENTIFIER_POINTER (declarator)[1] == '_' + && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0)) + && current_lang_name == lang_name_cplusplus + && ctype == NULL_TREE + /* NULL_TREE means global namespace. */ + && DECL_CONTEXT (decl) == NULL_TREE) + DECL_LANGUAGE (decl) = lang_c; + + /* Should probably propagate const out from type to decl I bet (mrs). */ + if (staticp) + { + DECL_STATIC_FUNCTION_P (decl) = 1; + DECL_CONTEXT (decl) = ctype; + } + + if (ctype) + DECL_CLASS_CONTEXT (decl) = ctype; + + if (ctype == NULL_TREE && DECL_MAIN_P (decl)) + { + if (processing_template_decl) + error ("cannot declare `main' to be a template"); + if (inlinep) + error ("cannot declare `main' to be inline"); + else if (! publicp) + error ("cannot declare `main' to be static"); + inlinep = 0; + publicp = 1; + } + + /* Members of anonymous types and local classes have no linkage; make + them internal. */ + if (ctype && (ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype)) + || hack_decl_function_context (TYPE_MAIN_DECL (ctype)))) + publicp = 0; + + if (publicp) + { + /* [basic.link]: A name with no linkage (notably, the name of a class + or enumeration declared in a local scope) shall not be used to + declare an entity with linkage. + + Only check this for public decls for now. */ + t = no_linkage_check (TREE_TYPE (decl)); + if (t) + { + if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) + { + if (DECL_LANGUAGE (decl) == lang_c) + /* Allow this; it's pretty common in C. */; + else + cp_pedwarn ("non-local function `%#D' uses anonymous type", + decl); + } + else + cp_pedwarn ("non-local function `%#D' uses local type `%T'", + decl, t); + } + } + + TREE_PUBLIC (decl) = publicp; + if (! publicp) + { + DECL_INTERFACE_KNOWN (decl) = 1; + DECL_NOT_REALLY_EXTERN (decl) = 1; + } + + if (inlinep) + DECL_THIS_INLINE (decl) = DECL_INLINE (decl) = 1; + + DECL_EXTERNAL (decl) = 1; + if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE) + { + cp_error ("%smember function `%D' cannot have `%T' method qualifier", + (ctype ? "static " : "non-"), decl, TREE_VALUE (quals)); + quals = NULL_TREE; + } + + if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) + grok_op_properties (decl, virtualp, check < 0); + + if (ctype && hack_decl_function_context (decl)) + DECL_NO_STATIC_CHAIN (decl) = 1; + + for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t)) + if (TREE_PURPOSE (t) + && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG) + { + has_default_arg = 1; + break; + } + + if (friendp + && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR) + { + if (funcdef_flag) + cp_error + ("defining explicit specialization `%D' in friend declaration", + orig_declarator); + else + { + if (PROCESSING_REAL_TEMPLATE_DECL_P ()) + { + /* Something like `template friend void f()'. */ + cp_error ("template-id `%D' in declaration of primary template", + orig_declarator); + return NULL_TREE; + } + + + /* A friend declaration of the form friend void f<>(). Record + the information in the TEMPLATE_ID_EXPR. */ + SET_DECL_IMPLICIT_INSTANTIATION (decl); + DECL_TEMPLATE_INFO (decl) + = perm_tree_cons (TREE_OPERAND (orig_declarator, 0), + TREE_OPERAND (orig_declarator, 1), + NULL_TREE); + + if (has_default_arg) + { + cp_error ("default arguments are not allowed in declaration of friend template specialization `%D'", + decl); + return NULL_TREE; + } + + if (inlinep) + { + cp_error ("`inline' is not allowed in declaration of friend template specialization `%D'", + decl); + return NULL_TREE; + } + } + } + + if (has_default_arg) + add_defarg_fn (decl); + + /* Plain overloading: will not be grok'd by grokclassfn. */ + if (! ctype && ! processing_template_decl + && DECL_LANGUAGE (decl) != lang_c + && (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1)) + set_mangled_name_for_decl (decl); + + if (funcdef_flag) + /* Make the init_value nonzero so pushdecl knows this is not + tentative. error_mark_node is replaced later with the BLOCK. */ + DECL_INITIAL (decl) = error_mark_node; + + /* Caller will do the rest of this. */ + if (check < 0) + return decl; + + if (check && funcdef_flag) + DECL_INITIAL (decl) = error_mark_node; + + if (flags == NO_SPECIAL && ctype && constructor_name (cname) == declarator) + { + tree tmp; + /* Just handle constructors here. We could do this + inside the following if stmt, but I think + that the code is more legible by breaking this + case out. See comments below for what each of + the following calls is supposed to do. */ + DECL_CONSTRUCTOR_P (decl) = 1; + + grokclassfn (ctype, decl, flags, quals); + + decl = check_explicit_specialization (orig_declarator, decl, + template_count, + 2 * (funcdef_flag != 0) + + 4 * (friendp != 0)); + if (decl == error_mark_node) + return NULL_TREE; + + if ((! TYPE_FOR_JAVA (ctype) || check_java_method (decl)) + && check) + { + tmp = check_classfn (ctype, decl); + + if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL) + tmp = DECL_TEMPLATE_RESULT(tmp); + + if (tmp && DECL_ARTIFICIAL (tmp)) + cp_error ("definition of implicitly-declared `%D'", tmp); + if (tmp && duplicate_decls (decl, tmp)) + return tmp; + } + if (! grok_ctor_properties (ctype, decl)) + return NULL_TREE; + } + else + { + tree tmp; + + /* Function gets the ugly name, field gets the nice one. + This call may change the type of the function (because + of default parameters)! */ + if (ctype != NULL_TREE) + grokclassfn (ctype, decl, flags, quals); + + decl = check_explicit_specialization (orig_declarator, decl, + template_count, + 2 * (funcdef_flag != 0) + + 4 * (friendp != 0)); + if (decl == error_mark_node) + return NULL_TREE; + + if (ctype != NULL_TREE + && (! TYPE_FOR_JAVA (ctype) || check_java_method (decl)) + && check) + { + tmp = check_classfn (ctype, decl); + + if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL) + tmp = DECL_TEMPLATE_RESULT (tmp); + + if (tmp && DECL_STATIC_FUNCTION_P (tmp) + && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) + { + /* Remove the `this' parm added by grokclassfn. + XXX Isn't this done in start_function, too? */ + revert_static_member_fn (&decl, NULL, NULL); + last_function_parms = TREE_CHAIN (last_function_parms); + } + if (tmp && DECL_ARTIFICIAL (tmp)) + cp_error ("definition of implicitly-declared `%D'", tmp); + if (tmp) + { + /* Attempt to merge the declarations. This can fail, in + the case of some illegal specialization declarations. */ + if (!duplicate_decls (decl, tmp)) + cp_error ("no `%#D' member function declared in class `%T'", + decl, ctype); + return tmp; + } + } + + if (ctype == NULL_TREE || check) + return decl; + + if (virtualp) + { + DECL_VIRTUAL_P (decl) = 1; + if (DECL_VINDEX (decl) == NULL_TREE) + DECL_VINDEX (decl) = error_mark_node; + IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; + } + } + return decl; +} + +static tree +grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace) + tree type; + tree declarator; + RID_BIT_TYPE *specbits_in; + int initialized; + int constp; + tree in_namespace; +{ + tree decl; + RID_BIT_TYPE specbits; + + specbits = *specbits_in; + + if (TREE_CODE (type) == OFFSET_TYPE) + { + /* If you declare a static member so that it + can be initialized, the code will reach here. */ + tree basetype = TYPE_OFFSET_BASETYPE (type); + type = TREE_TYPE (type); + decl = build_lang_field_decl (VAR_DECL, declarator, type); + DECL_CONTEXT (decl) = basetype; + DECL_CLASS_CONTEXT (decl) = basetype; + DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator); + } + else + { + tree context; + + if (in_namespace) + context = in_namespace; + else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits)) + context = current_namespace; + else + context = NULL_TREE; + + decl = build_decl (VAR_DECL, declarator, complete_type (type)); + + if (context) + set_decl_namespace (decl, context, 0); + + context = DECL_CONTEXT (decl); + if (declarator && context && current_lang_name != lang_name_c) + DECL_ASSEMBLER_NAME (decl) = build_static_name (context, declarator); + } + + if (in_namespace) + set_decl_namespace (decl, in_namespace, 0); + + if (RIDBIT_SETP (RID_EXTERN, specbits)) + { + DECL_THIS_EXTERN (decl) = 1; + DECL_EXTERNAL (decl) = !initialized; + } + + /* In class context, static means one per class, + public access, and static storage. */ + if (DECL_CLASS_SCOPE_P (decl)) + { + TREE_PUBLIC (decl) = 1; + TREE_STATIC (decl) = 1; + DECL_EXTERNAL (decl) = 0; + } + /* At top level, either `static' or no s.c. makes a definition + (perhaps tentative), and absence of `static' makes it public. */ + else if (toplevel_bindings_p ()) + { + TREE_PUBLIC (decl) = (RIDBIT_NOTSETP (RID_STATIC, specbits) + && (DECL_THIS_EXTERN (decl) || ! constp)); + TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); + } + /* Not at top level, only `static' makes a static definition. */ + else + { + TREE_STATIC (decl) = !! RIDBIT_SETP (RID_STATIC, specbits); + TREE_PUBLIC (decl) = DECL_EXTERNAL (decl); + } + + if (TREE_PUBLIC (decl)) + { + /* [basic.link]: A name with no linkage (notably, the name of a class + or enumeration declared in a local scope) shall not be used to + declare an entity with linkage. + + Only check this for public decls for now. */ + tree t = no_linkage_check (TREE_TYPE (decl)); + if (t) + { + if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) + /* Ignore for now; `enum { foo } e' is pretty common. */; + else + cp_pedwarn ("non-local variable `%#D' uses local type `%T'", + decl, t); + } + } + + return decl; +} + +/* Create and return a canonical pointer to member function type, for + TYPE, which is a POINTER_TYPE to a METHOD_TYPE. */ + +tree +build_ptrmemfunc_type (type) + tree type; +{ + tree fields[4]; + tree t; + tree u; + + /* If a canonical type already exists for this type, use it. We use + this method instead of type_hash_canon, because it only does a + simple equality check on the list of field members. */ + + if ((t = TYPE_GET_PTRMEMFUNC_TYPE (type))) + return t; + + push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type)); + + u = make_lang_type (UNION_TYPE); + SET_IS_AGGR_TYPE (u, 0); + fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type); + fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier, + delta_type_node); + finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node); + TYPE_NAME (u) = NULL_TREE; + + t = make_lang_type (RECORD_TYPE); + + /* Let the front-end know this is a pointer to member function... */ + TYPE_PTRMEMFUNC_FLAG (t) = 1; + /* ... and not really an aggregate. */ + SET_IS_AGGR_TYPE (t, 0); + + fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, + delta_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, + delta_type_node); + fields[2] = build_lang_field_decl (FIELD_DECL, pfn_or_delta2_identifier, u); + finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node); + + pop_obstacks (); + + /* Zap out the name so that the back-end will give us the debugging + information for this anonymous RECORD_TYPE. */ + TYPE_NAME (t) = NULL_TREE; + + TYPE_SET_PTRMEMFUNC_TYPE (type, t); + + /* Seems to be wanted. */ + CLASSTYPE_GOT_SEMICOLON (t) = 1; + return t; +} + +/* DECL is a VAR_DECL defined in-class, whose TYPE is also given. + Check to see that the definition is valid. Issue appropriate error + messages. Return 1 if the definition is particularly bad, or 0 + otherwise. */ + +int +check_static_variable_definition (decl, type) + tree decl; + tree type; +{ + /* Motion 10 at San Diego: If a static const integral data member is + initialized with an integral constant expression, the initializer + may appear either in the declaration (within the class), or in + the definition, but not both. If it appears in the class, the + member is a member constant. The file-scope definition is always + required. */ + if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE) + { + cp_error ("in-class initialization of static data member of non-integral type `%T'", + type); + /* If we just return the declaration, crashes will sometimes + occur. We therefore return void_type_node, as if this was a + friend declaration, to cause callers to completely ignore + this declaration. */ + return 1; + } + else if (!CP_TYPE_CONST_P (type)) + cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'", + decl); + else if (pedantic && !INTEGRAL_TYPE_P (type)) + cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type); + + return 0; +} + +/* Given declspecs and a declarator, + determine the name and type of the object declared + and construct a ..._DECL node for it. + (In one case we can return a ..._TYPE node instead. + For invalid input we sometimes return 0.) + + DECLSPECS is a chain of tree_list nodes whose value fields + are the storage classes and type specifiers. + + DECL_CONTEXT says which syntactic context this declaration is in: + NORMAL for most contexts. Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL. + FUNCDEF for a function definition. Like NORMAL but a few different + error messages in each case. Return value may be zero meaning + this definition is too screwy to try to parse. + MEMFUNCDEF for a function definition. Like FUNCDEF but prepares to + handle member functions (which have FIELD context). + Return value may be zero meaning this definition is too screwy to + try to parse. + PARM for a parameter declaration (either within a function prototype + or before a function body). Make a PARM_DECL, or return void_type_node. + CATCHPARM for a parameter declaration before a catch clause. + TYPENAME if for a typename (in a cast or sizeof). + Don't make a DECL node; just return the ..._TYPE node. + FIELD for a struct or union field; make a FIELD_DECL. + BITFIELD for a field with specified width. + INITIALIZED is 1 if the decl has an initializer. + + ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and + normal attributes in TREE_PURPOSE, or NULL_TREE. + + In the TYPENAME case, DECLARATOR is really an absolute declarator. + It may also be so in the PARM case, for a prototype where the + argument type is specified but not the name. + + This function is where the complicated C meanings of `static' + and `extern' are interpreted. + + For C++, if there is any monkey business to do, the function which + calls this one must do it, i.e., prepending instance variables, + renaming overloaded function names, etc. + + Note that for this C++, it is an error to define a method within a class + which does not belong to that class. + + Except in the case where SCOPE_REFs are implicitly known (such as + methods within a class being redundantly qualified), + declarations which involve SCOPE_REFs are returned as SCOPE_REFs + (class_name::decl_name). The caller must also deal with this. + + If a constructor or destructor is seen, and the context is FIELD, + then the type gains the attribute TREE_HAS_x. If such a declaration + is erroneous, NULL_TREE is returned. + + QUALS is used only for FUNCDEF and MEMFUNCDEF cases. For a member + function, these are the qualifiers to give to the `this' pointer. + + May return void_type_node if the declarator turned out to be a friend. + See grokfield for details. */ + +enum return_types { return_normal, return_ctor, return_dtor, return_conversion }; + +tree +grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) + tree declspecs; + tree declarator; + enum decl_context decl_context; + int initialized; + tree attrlist; +{ + RID_BIT_TYPE specbits; + int nclasses = 0; + tree spec; + tree type = NULL_TREE; + int longlong = 0; + int constp; + int restrictp; + int volatilep; + int type_quals; + int virtualp, explicitp, friendp, inlinep, staticp; + int explicit_int = 0; + int explicit_char = 0; + int defaulted_int = 0; + int opaque_typedef = 0; + tree typedef_decl = NULL_TREE; + char *name; + tree typedef_type = NULL_TREE; + int funcdef_flag = 0; + enum tree_code innermost_code = ERROR_MARK; + int bitfield = 0; +#if 0 + /* See the code below that used this. */ + tree decl_machine_attr = NULL_TREE; +#endif + /* Set this to error_mark_node for FIELD_DECLs we could not handle properly. + All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */ + tree init = NULL_TREE; + + /* Keep track of what sort of function is being processed + so that we can warn about default return values, or explicit + return values which do not match prescribed defaults. */ + enum return_types return_type = return_normal; + + tree dname = NULL_TREE; + tree ctype = current_class_type; + tree ctor_return_type = NULL_TREE; + enum overload_flags flags = NO_SPECIAL; + tree quals = NULL_TREE; + tree raises = NULL_TREE; + int template_count = 0; + tree in_namespace = NULL_TREE; + tree inner_attrs; + int ignore_attrs; + + RIDBIT_RESET_ALL (specbits); + if (decl_context == FUNCDEF) + funcdef_flag = 1, decl_context = NORMAL; + else if (decl_context == MEMFUNCDEF) + funcdef_flag = -1, decl_context = FIELD; + else if (decl_context == BITFIELD) + bitfield = 1, decl_context = FIELD; + + /* Look inside a declarator for the name being declared + and get it as a string, for an error message. */ + { + tree *next = &declarator; + register tree decl; + name = NULL; + + while (next && *next) + { + decl = *next; + switch (TREE_CODE (decl)) + { + case TREE_LIST: + /* For attributes. */ + next = &TREE_VALUE (decl); + break; + + case COND_EXPR: + ctype = NULL_TREE; + next = &TREE_OPERAND (decl, 0); + break; + + case BIT_NOT_EXPR: /* For C++ destructors! */ + { + tree name = TREE_OPERAND (decl, 0); + tree rename = NULL_TREE; + + my_friendly_assert (flags == NO_SPECIAL, 152); + flags = DTOR_FLAG; + return_type = return_dtor; + if (TREE_CODE (name) == TYPE_DECL) + TREE_OPERAND (decl, 0) = name = constructor_name (name); + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153); + if (ctype == NULL_TREE) + { + if (current_class_type == NULL_TREE) + { + error ("destructors must be member functions"); + flags = NO_SPECIAL; + } + else + { + tree t = constructor_name (current_class_name); + if (t != name) + rename = t; + } + } + else + { + tree t = constructor_name (ctype); + if (t != name) + rename = t; + } + + if (rename) + { + cp_error ("destructor `%T' must match class name `%T'", + name, rename); + TREE_OPERAND (decl, 0) = rename; + } + next = &name; + } + break; + + case ADDR_EXPR: /* C++ reference declaration */ + /* Fall through. */ + case ARRAY_REF: + case INDIRECT_REF: + ctype = NULL_TREE; + innermost_code = TREE_CODE (decl); + next = &TREE_OPERAND (decl, 0); + break; + + case CALL_EXPR: + if (parmlist_is_exprlist (TREE_OPERAND (decl, 1))) + { + /* This is actually a variable declaration using + constructor syntax. We need to call start_decl and + cp_finish_decl so we can get the variable + initialized... */ + + tree attributes, prefix_attributes; + + *next = TREE_OPERAND (decl, 0); + init = TREE_OPERAND (decl, 1); + + if (attrlist) + { + attributes = TREE_PURPOSE (attrlist); + prefix_attributes = TREE_VALUE (attrlist); + } + else + { + attributes = NULL_TREE; + prefix_attributes = NULL_TREE; + } + + decl = start_decl (declarator, declspecs, 1, + attributes, prefix_attributes); + if (decl) + { + /* Look for __unused__ attribute */ + if (TREE_USED (TREE_TYPE (decl))) + TREE_USED (decl) = 1; + finish_decl (decl, init, NULL_TREE); + } + else + cp_error ("invalid declarator"); + return 0; + } + innermost_code = TREE_CODE (decl); + if (decl_context == FIELD && ctype == NULL_TREE) + ctype = current_class_type; + if (ctype + && TREE_OPERAND (decl, 0) + && (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL + && ((DECL_NAME (TREE_OPERAND (decl, 0)) + == constructor_name_full (ctype)) + || (DECL_NAME (TREE_OPERAND (decl, 0)) + == constructor_name (ctype))))) + TREE_OPERAND (decl, 0) = constructor_name (ctype); + next = &TREE_OPERAND (decl, 0); + decl = *next; + if (ctype != NULL_TREE + && decl != NULL_TREE && flags != DTOR_FLAG + && decl == constructor_name (ctype)) + { + return_type = return_ctor; + ctor_return_type = ctype; + } + ctype = NULL_TREE; + break; + + case TEMPLATE_ID_EXPR: + { + tree fns = TREE_OPERAND (decl, 0); + + if (TREE_CODE (fns) == LOOKUP_EXPR) + fns = TREE_OPERAND (fns, 0); + + dname = fns; + if (TREE_CODE (dname) == COMPONENT_REF) + dname = TREE_OPERAND (dname, 1); + if (TREE_CODE (dname) != IDENTIFIER_NODE) + { + my_friendly_assert (is_overloaded_fn (dname), + 19990331); + dname = DECL_NAME (get_first_fn (dname)); + } + } + /* Fall through. */ + + case IDENTIFIER_NODE: + if (TREE_CODE (decl) == IDENTIFIER_NODE) + dname = decl; + + next = 0; + + if (is_rid (dname)) + { + cp_error ("declarator-id missing; using reserved word `%D'", + dname); + name = IDENTIFIER_POINTER (dname); + } + if (! IDENTIFIER_OPNAME_P (dname) + /* GNU/Linux headers use '__op'. Arrgh. */ + || (IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname))) + name = IDENTIFIER_POINTER (dname); + else + { + if (IDENTIFIER_TYPENAME_P (dname)) + { + my_friendly_assert (flags == NO_SPECIAL, 154); + flags = TYPENAME_FLAG; + ctor_return_type = TREE_TYPE (dname); + return_type = return_conversion; + } + name = operator_name_string (dname); + } + break; + + /* C++ extension */ + case SCOPE_REF: + { + /* Perform error checking, and decide on a ctype. */ + tree cname = TREE_OPERAND (decl, 0); + if (cname == NULL_TREE) + ctype = NULL_TREE; + else if (TREE_CODE (cname) == NAMESPACE_DECL) + { + ctype = NULL_TREE; + in_namespace = TREE_OPERAND (decl, 0); + TREE_OPERAND (decl, 0) = NULL_TREE; + } + else if (! is_aggr_type (cname, 1)) + TREE_OPERAND (decl, 0) = NULL_TREE; + /* Must test TREE_OPERAND (decl, 1), in case user gives + us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */ + else if (TREE_OPERAND (decl, 1) + && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF) + ctype = cname; + else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM + || TREE_CODE (cname) == TEMPLATE_TEMPLATE_PARM) + { + cp_error ("`%T::%D' is not a valid declarator", cname, + TREE_OPERAND (decl, 1)); + cp_error (" perhaps you want `typename %T::%D' to make it a type", + cname, TREE_OPERAND (decl, 1)); + return void_type_node; + } + else if (ctype == NULL_TREE) + ctype = cname; + else if (TREE_COMPLEXITY (decl) == current_class_depth) + TREE_OPERAND (decl, 0) = ctype; + else + { + if (! UNIQUELY_DERIVED_FROM_P (cname, ctype)) + { + cp_error ("type `%T' is not derived from type `%T'", + cname, ctype); + TREE_OPERAND (decl, 0) = NULL_TREE; + } + else + ctype = cname; + } + + if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL + && ((DECL_NAME (TREE_OPERAND (decl, 1)) + == constructor_name_full (ctype)) + || (DECL_NAME (TREE_OPERAND (decl, 1)) + == constructor_name (ctype)))) + TREE_OPERAND (decl, 1) = constructor_name (ctype); + next = &TREE_OPERAND (decl, 1); + decl = *next; + if (ctype) + { + if (TREE_CODE (decl) == IDENTIFIER_NODE + && constructor_name (ctype) == decl) + { + return_type = return_ctor; + ctor_return_type = ctype; + } + else if (TREE_CODE (decl) == BIT_NOT_EXPR + && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE + && (constructor_name (ctype) == TREE_OPERAND (decl, 0) + || constructor_name_full (ctype) == TREE_OPERAND (decl, 0))) + { + return_type = return_dtor; + ctor_return_type = ctype; + flags = DTOR_FLAG; + TREE_OPERAND (decl, 0) = constructor_name (ctype); + next = &TREE_OPERAND (decl, 0); + } + } + } + break; + + case ERROR_MARK: + next = 0; + break; + + case TYPE_DECL: + /* Parse error puts this typespec where + a declarator should go. */ + cp_error ("`%T' specified as declarator-id", DECL_NAME (decl)); + if (TREE_TYPE (decl) == current_class_type) + cp_error (" perhaps you want `%T' for a constructor", + current_class_name); + dname = DECL_NAME (decl); + name = IDENTIFIER_POINTER (dname); + + /* Avoid giving two errors for this. */ + IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE; + + declspecs = temp_tree_cons (NULL_TREE, integer_type_node, + declspecs); + *next = dname; + next = 0; + break; + + default: + cp_compiler_error ("`%D' as declarator", decl); + return 0; /* We used to do a 155 abort here. */ + } + } + if (name == NULL) + name = "type name"; + } + + /* A function definition's declarator must have the form of + a function declarator. */ + + if (funcdef_flag && innermost_code != CALL_EXPR) + return 0; + + if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG) + && innermost_code != CALL_EXPR + && ! (ctype && declspecs == NULL_TREE)) + { + cp_error ("declaration of `%D' as non-function", dname); + return void_type_node; + } + + /* Anything declared one level down from the top level + must be one of the parameters of a function + (because the body is at least two levels down). */ + + /* This heuristic cannot be applied to C++ nodes! Fixed, however, + by not allowing C++ class definitions to specify their parameters + with xdecls (must be spec.d in the parmlist). + + Since we now wait to push a class scope until we are sure that + we are in a legitimate method context, we must set oldcname + explicitly (since current_class_name is not yet alive). + + We also want to avoid calling this a PARM if it is in a namespace. */ + + if (decl_context == NORMAL && ! namespace_bindings_p () + && ! pseudo_global_level_p ()) + { + struct binding_level *b = current_binding_level; + current_binding_level = b->level_chain; + if (current_binding_level != 0 && toplevel_bindings_p ()) + decl_context = PARM; + current_binding_level = b; + } + + /* Look through the decl specs and record which ones appear. + Some typespecs are defined as built-in typenames. + Others, the ones that are modifiers of other types, + are represented by bits in SPECBITS: set the bits for + the modifiers that appear. Storage class keywords are also in SPECBITS. + + If there is a typedef name or a type, store the type in TYPE. + This includes builtin typedefs such as `int'. + + Set EXPLICIT_INT if the type is `int' or `char' and did not + come from a user typedef. + + Set LONGLONG if `long' is mentioned twice. + + For C++, constructors and destructors have their own fast treatment. */ + + for (spec = declspecs; spec; spec = TREE_CHAIN (spec)) + { + register int i; + register tree id; + + /* Certain parse errors slip through. For example, + `int class;' is not caught by the parser. Try + weakly to recover here. */ + if (TREE_CODE (spec) != TREE_LIST) + return 0; + + id = TREE_VALUE (spec); + + if (TREE_CODE (id) == IDENTIFIER_NODE) + { + if (id == ridpointers[(int) RID_INT] + || id == ridpointers[(int) RID_CHAR] + || id == ridpointers[(int) RID_BOOL] + || id == ridpointers[(int) RID_WCHAR]) + { + if (type) + { + if (id == ridpointers[(int) RID_BOOL]) + error ("`bool' is now a keyword"); + else + cp_error ("extraneous `%T' ignored", id); + } + else + { + if (id == ridpointers[(int) RID_INT]) + explicit_int = 1; + else if (id == ridpointers[(int) RID_CHAR]) + explicit_char = 1; + type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id)); + } + goto found; + } + /* C++ aggregate types. */ + if (IDENTIFIER_HAS_TYPE_VALUE (id)) + { + if (type) + cp_error ("multiple declarations `%T' and `%T'", type, id); + else + type = IDENTIFIER_TYPE_VALUE (id); + goto found; + } + + for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++) + { + if (ridpointers[i] == id) + { + if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits)) + { + if (pedantic && ! in_system_header && warn_long_long) + pedwarn ("ANSI C++ does not support `long long'"); + if (longlong) + error ("`long long long' is too long for GCC"); + else + longlong = 1; + } + else if (RIDBIT_SETP (i, specbits)) + pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); + RIDBIT_SET (i, specbits); + goto found; + } + } + } + /* C++ aggregate types. */ + else if (TREE_CODE (id) == TYPE_DECL || TREE_CODE (id) == TEMPLATE_DECL) + { + if (type) + cp_error ("multiple declarations `%T' and `%T'", type, + TREE_TYPE (id)); + else + { + type = TREE_TYPE (id); + TREE_VALUE (spec) = type; + } + goto found; + } + if (type) + error ("two or more data types in declaration of `%s'", name); + else if (TREE_CODE (id) == IDENTIFIER_NODE) + { + register tree t = lookup_name (id, 1); + if (!t || TREE_CODE (t) != TYPE_DECL) + error ("`%s' fails to be a typedef or built in type", + IDENTIFIER_POINTER (id)); + else + { + type = TREE_TYPE (t); +#if 0 + /* See the code below that used this. */ + decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id); +#endif + typedef_decl = t; + } + } + else if (id != error_mark_node) + /* Can't change CLASS nodes into RECORD nodes here! */ + type = id; + + found: ; + } + + typedef_type = type; + + /* No type at all: default to `int', and set DEFAULTED_INT + because it was not a user-defined typedef. + Except when we have a `typedef' inside a signature, in + which case the type defaults to `unknown type' and is + instantiated when assigning to a signature pointer or ref. */ + + if (type == NULL_TREE + && (RIDBIT_SETP (RID_SIGNED, specbits) + || RIDBIT_SETP (RID_UNSIGNED, specbits) + || RIDBIT_SETP (RID_LONG, specbits) + || RIDBIT_SETP (RID_SHORT, specbits))) + { + /* These imply 'int'. */ + type = integer_type_node; + defaulted_int = 1; + } + + if (type == NULL_TREE) + { + explicit_int = -1; + if (return_type == return_dtor) + type = void_type_node; + else if (return_type == return_ctor) + type = build_pointer_type (ctor_return_type); + else if (return_type == return_conversion) + type = ctor_return_type; + else if (current_class_type + && IS_SIGNATURE (current_class_type) + && RIDBIT_SETP (RID_TYPEDEF, specbits) + && (decl_context == FIELD || decl_context == NORMAL)) + { + explicit_int = 0; + opaque_typedef = 1; + type = copy_node (opaque_type_node); + } + else + { + /* We handle `main' specially here, because 'main () { }' is so + common. With no options, it is allowed. With -Wreturn-type, + it is a warning. It is only an error with -pedantic-errors. */ + int is_main = (funcdef_flag + && MAIN_NAME_P (dname) + && ctype == NULL_TREE + && in_namespace == NULL_TREE + && current_namespace == global_namespace); + + if (in_system_header) + /* Allow it, sigh. */; + else if (pedantic || ! is_main) + cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type", + dname); + else if (warn_return_type) + cp_warning ("ANSI C++ forbids declaration `%D' with no type", + dname); + + type = integer_type_node; + } + } + else if (return_type == return_dtor) + { + error ("return type specification for destructor invalid"); + type = void_type_node; + } + else if (return_type == return_ctor) + { + error ("return type specification for constructor invalid"); + type = build_pointer_type (ctor_return_type); + } + else if (return_type == return_conversion) + { + if (!same_type_p (type, ctor_return_type)) + cp_error ("operator `%T' declared to return `%T'", + ctor_return_type, type); + else + cp_pedwarn ("return type specified for `operator %T'", + ctor_return_type); + + type = ctor_return_type; + } + + ctype = NULL_TREE; + + /* Now process the modifiers that were specified + and check for invalid combinations. */ + + /* Long double is a special combination. */ + + if (RIDBIT_SETP (RID_LONG, specbits) + && TYPE_MAIN_VARIANT (type) == double_type_node) + { + RIDBIT_RESET (RID_LONG, specbits); + type = build_qualified_type (long_double_type_node, + CP_TYPE_QUALS (type)); + } + + /* Check all other uses of type modifiers. */ + + if (RIDBIT_SETP (RID_UNSIGNED, specbits) + || RIDBIT_SETP (RID_SIGNED, specbits) + || RIDBIT_SETP (RID_LONG, specbits) + || RIDBIT_SETP (RID_SHORT, specbits)) + { + int ok = 0; + + if (TREE_CODE (type) == REAL_TYPE) + error ("short, signed or unsigned invalid for `%s'", name); + else if (TREE_CODE (type) != INTEGER_TYPE) + error ("long, short, signed or unsigned invalid for `%s'", name); + else if (RIDBIT_SETP (RID_LONG, specbits) + && RIDBIT_SETP (RID_SHORT, specbits)) + error ("long and short specified together for `%s'", name); + else if ((RIDBIT_SETP (RID_LONG, specbits) + || RIDBIT_SETP (RID_SHORT, specbits)) + && explicit_char) + error ("long or short specified with char for `%s'", name); + else if ((RIDBIT_SETP (RID_LONG, specbits) + || RIDBIT_SETP (RID_SHORT, specbits)) + && TREE_CODE (type) == REAL_TYPE) + error ("long or short specified with floating type for `%s'", name); + else if (RIDBIT_SETP (RID_SIGNED, specbits) + && RIDBIT_SETP (RID_UNSIGNED, specbits)) + error ("signed and unsigned given together for `%s'", name); + else + { + ok = 1; + if (!explicit_int && !defaulted_int && !explicit_char && pedantic) + { + pedwarn ("long, short, signed or unsigned used invalidly for `%s'", + name); + if (flag_pedantic_errors) + ok = 0; + } + } + + /* Discard the type modifiers if they are invalid. */ + if (! ok) + { + RIDBIT_RESET (RID_UNSIGNED, specbits); + RIDBIT_RESET (RID_SIGNED, specbits); + RIDBIT_RESET (RID_LONG, specbits); + RIDBIT_RESET (RID_SHORT, specbits); + longlong = 0; + } + } + + if (RIDBIT_SETP (RID_COMPLEX, specbits) + && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) + { + error ("complex invalid for `%s'", name); + RIDBIT_RESET (RID_COMPLEX, specbits); + } + + /* Decide whether an integer type is signed or not. + Optionally treat bitfields as signed by default. */ + if (RIDBIT_SETP (RID_UNSIGNED, specbits) + || (bitfield && ! flag_signed_bitfields + && (explicit_int || defaulted_int || explicit_char + /* A typedef for plain `int' without `signed' + can be controlled just like plain `int'. */ + || ! (typedef_decl != NULL_TREE + && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) + && TREE_CODE (type) != ENUMERAL_TYPE + && RIDBIT_NOTSETP (RID_SIGNED, specbits))) + { + if (longlong) + type = long_long_unsigned_type_node; + else if (RIDBIT_SETP (RID_LONG, specbits)) + type = long_unsigned_type_node; + else if (RIDBIT_SETP (RID_SHORT, specbits)) + type = short_unsigned_type_node; + else if (type == char_type_node) + type = unsigned_char_type_node; + else if (typedef_decl) + type = unsigned_type (type); + else + type = unsigned_type_node; + } + else if (RIDBIT_SETP (RID_SIGNED, specbits) + && type == char_type_node) + type = signed_char_type_node; + else if (longlong) + type = long_long_integer_type_node; + else if (RIDBIT_SETP (RID_LONG, specbits)) + type = long_integer_type_node; + else if (RIDBIT_SETP (RID_SHORT, specbits)) + type = short_integer_type_node; + + if (RIDBIT_SETP (RID_COMPLEX, specbits)) + { + /* If we just have "complex", it is equivalent to + "complex double", but if any modifiers at all are specified it is + the complex form of TYPE. E.g, "complex short" is + "complex short int". */ + + if (defaulted_int && ! longlong + && ! (RIDBIT_SETP (RID_LONG, specbits) + || RIDBIT_SETP (RID_SHORT, specbits) + || RIDBIT_SETP (RID_SIGNED, specbits) + || RIDBIT_SETP (RID_UNSIGNED, specbits))) + type = complex_double_type_node; + else if (type == integer_type_node) + type = complex_integer_type_node; + else if (type == float_type_node) + type = complex_float_type_node; + else if (type == double_type_node) + type = complex_double_type_node; + else if (type == long_double_type_node) + type = complex_long_double_type_node; + else + type = build_complex_type (type); + } + + if (return_type == return_conversion + && (RIDBIT_SETP (RID_CONST, specbits) + || RIDBIT_SETP (RID_VOLATILE, specbits) + || RIDBIT_SETP (RID_RESTRICT, specbits))) + cp_error ("qualifiers are not allowed on declaration of `operator %T'", + ctor_return_type); + + /* Set CONSTP if this declaration is `const', whether by + explicit specification or via a typedef. + Likewise for VOLATILEP. */ + + constp = !! RIDBIT_SETP (RID_CONST, specbits) + CP_TYPE_CONST_P (type); + restrictp = + !! RIDBIT_SETP (RID_RESTRICT, specbits) + CP_TYPE_RESTRICT_P (type); + volatilep = + !! RIDBIT_SETP (RID_VOLATILE, specbits) + CP_TYPE_VOLATILE_P (type); + type_quals = ((constp ? TYPE_QUAL_CONST : 0) + | (restrictp ? TYPE_QUAL_RESTRICT : 0) + | (volatilep ? TYPE_QUAL_VOLATILE : 0)); + type = cp_build_qualified_type (type, type_quals); + staticp = 0; + inlinep = !! RIDBIT_SETP (RID_INLINE, specbits); + virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits); + RIDBIT_RESET (RID_VIRTUAL, specbits); + explicitp = RIDBIT_SETP (RID_EXPLICIT, specbits) != 0; + RIDBIT_RESET (RID_EXPLICIT, specbits); + + if (RIDBIT_SETP (RID_STATIC, specbits)) + staticp = 1 + (decl_context == FIELD); + + if (virtualp && staticp == 2) + { + cp_error ("member `%D' cannot be declared both virtual and static", + dname); + staticp = 0; + } + friendp = RIDBIT_SETP (RID_FRIEND, specbits); + RIDBIT_RESET (RID_FRIEND, specbits); + + /* $7.1.2, Function specifiers */ + if (friendp && explicitp) + error ("only declarations of constructors can be `explicit'"); + + if (RIDBIT_SETP (RID_MUTABLE, specbits)) + { + if (decl_context == PARM) + { + error ("non-member `%s' cannot be declared `mutable'", name); + RIDBIT_RESET (RID_MUTABLE, specbits); + } + else if (friendp || decl_context == TYPENAME) + { + error ("non-object member `%s' cannot be declared `mutable'", name); + RIDBIT_RESET (RID_MUTABLE, specbits); + } + } + + /* Warn if two storage classes are given. Default to `auto'. */ + + if (RIDBIT_ANY_SET (specbits)) + { + if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++; + if (RIDBIT_SETP (RID_EXTERN, specbits)) nclasses++; + if (decl_context == PARM && nclasses > 0) + error ("storage class specifiers invalid in parameter declarations"); + if (RIDBIT_SETP (RID_TYPEDEF, specbits)) + { + if (decl_context == PARM) + error ("typedef declaration invalid in parameter declaration"); + nclasses++; + } + if (RIDBIT_SETP (RID_AUTO, specbits)) nclasses++; + if (RIDBIT_SETP (RID_REGISTER, specbits)) nclasses++; + } + + /* Give error if `virtual' is used outside of class declaration. */ + if (virtualp + && (current_class_name == NULL_TREE || decl_context != FIELD)) + { + error ("virtual outside class declaration"); + virtualp = 0; + } + if (current_class_name == NULL_TREE && RIDBIT_SETP (RID_MUTABLE, specbits)) + { + error ("only members can be declared mutable"); + RIDBIT_RESET (RID_MUTABLE, specbits); + } + + /* Static anonymous unions are dealt with here. */ + if (staticp && decl_context == TYPENAME + && TREE_CODE (declspecs) == TREE_LIST + && ANON_UNION_TYPE_P (TREE_VALUE (declspecs))) + decl_context = FIELD; + + /* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual' + is used in a signature member function declaration. */ + if (decl_context == FIELD + && IS_SIGNATURE (current_class_type) + && RIDBIT_NOTSETP (RID_TYPEDEF, specbits)) + { + if (type_quals != TYPE_UNQUALIFIED) + { + error ("type qualifiers specified for signature member function `%s'", name); + type_quals = TYPE_UNQUALIFIED; + } + if (inlinep) + { + error ("`inline' specified for signature member function `%s'", name); + /* Later, we'll make signature member functions inline. */ + inlinep = 0; + } + if (friendp) + { + error ("`friend' declaration in signature definition"); + friendp = 0; + } + if (virtualp) + { + error ("`virtual' specified for signature member function `%s'", + name); + /* Later, we'll make signature member functions virtual. */ + virtualp = 0; + } + } + + /* Warn about storage classes that are invalid for certain + kinds of declarations (parameters, typenames, etc.). */ + + if (nclasses > 1) + error ("multiple storage classes in declaration of `%s'", name); + else if (decl_context != NORMAL && nclasses > 0) + { + if ((decl_context == PARM || decl_context == CATCHPARM) + && (RIDBIT_SETP (RID_REGISTER, specbits) + || RIDBIT_SETP (RID_AUTO, specbits))) + ; + else if (RIDBIT_SETP (RID_TYPEDEF, specbits)) + ; + else if (decl_context == FIELD + && ! IS_SIGNATURE (current_class_type) + /* C++ allows static class elements */ + && RIDBIT_SETP (RID_STATIC, specbits)) + /* C++ also allows inlines and signed and unsigned elements, + but in those cases we don't come in here. */ + ; + else + { + if (decl_context == FIELD) + { + tree tmp = NULL_TREE; + register int op = 0; + + if (declarator) + { + /* Avoid trying to get an operand off an identifier node. */ + if (TREE_CODE (declarator) == IDENTIFIER_NODE) + tmp = declarator; + else + tmp = TREE_OPERAND (declarator, 0); + op = IDENTIFIER_OPNAME_P (tmp); + } + error ("storage class specified for %s `%s'", + IS_SIGNATURE (current_class_type) + ? (op + ? "signature member operator" + : "signature member function") + : (op ? "member operator" : "field"), + op ? operator_name_string (tmp) : name); + } + else + error (((decl_context == PARM || decl_context == CATCHPARM) + ? "storage class specified for parameter `%s'" + : "storage class specified for typename"), name); + RIDBIT_RESET (RID_REGISTER, specbits); + RIDBIT_RESET (RID_AUTO, specbits); + RIDBIT_RESET (RID_EXTERN, specbits); + + if (decl_context == FIELD && IS_SIGNATURE (current_class_type)) + { + RIDBIT_RESET (RID_STATIC, specbits); + staticp = 0; + } + } + } + else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag) + { + if (toplevel_bindings_p ()) + { + /* It's common practice (and completely valid) to have a const + be initialized and declared extern. */ + if (!(type_quals & TYPE_QUAL_CONST)) + warning ("`%s' initialized and declared `extern'", name); + } + else + error ("`%s' has both `extern' and initializer", name); + } + else if (RIDBIT_SETP (RID_EXTERN, specbits) && funcdef_flag + && ! toplevel_bindings_p ()) + error ("nested function `%s' declared `extern'", name); + else if (toplevel_bindings_p ()) + { + if (RIDBIT_SETP (RID_AUTO, specbits)) + error ("top-level declaration of `%s' specifies `auto'", name); + } + + if (nclasses > 0 && friendp) + error ("storage class specifiers invalid in friend function declarations"); + + /* Now figure out the structure of the declarator proper. + Descend through it, creating more complex types, until we reach + the declared identifier (or NULL_TREE, in an absolute declarator). */ + + inner_attrs = NULL_TREE; + ignore_attrs = 0; + + while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE + && TREE_CODE (declarator) != TEMPLATE_ID_EXPR) + { + /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]), + an INDIRECT_REF (for *...), + a CALL_EXPR (for ...(...)), + an identifier (for the name being declared) + or a null pointer (for the place in an absolute declarator + where the name was omitted). + For the last two cases, we have just exited the loop. + + For C++ it could also be + a SCOPE_REF (for class :: ...). In this case, we have converted + sensible names to types, and those are the values we use to + qualify the member name. + an ADDR_EXPR (for &...), + a BIT_NOT_EXPR (for destructors) + + At this point, TYPE is the type of elements of an array, + or for a function to return, or for a pointer to point to. + After this sequence of ifs, TYPE is the type of the + array or function or pointer, and DECLARATOR has had its + outermost layer removed. */ + + if (type == error_mark_node) + { + if (TREE_CODE (declarator) == SCOPE_REF) + declarator = TREE_OPERAND (declarator, 1); + else + declarator = TREE_OPERAND (declarator, 0); + continue; + } + if (quals != NULL_TREE + && (declarator == NULL_TREE + || TREE_CODE (declarator) != SCOPE_REF)) + { + if (ctype == NULL_TREE && TREE_CODE (type) == METHOD_TYPE) + ctype = TYPE_METHOD_BASETYPE (type); + if (ctype != NULL_TREE) + { + tree dummy = build_decl (TYPE_DECL, NULL_TREE, type); + ctype = grok_method_quals (ctype, dummy, quals); + type = TREE_TYPE (dummy); + quals = NULL_TREE; + } + } + + /* See the comment for the TREE_LIST case, below. */ + if (ignore_attrs) + ignore_attrs = 0; + else if (inner_attrs) + { + decl_attributes (type, inner_attrs, NULL_TREE); + inner_attrs = NULL_TREE; + } + + switch (TREE_CODE (declarator)) + { + case TREE_LIST: + { + /* We encode a declarator with embedded attributes using + a TREE_LIST. The attributes apply to the declarator + directly inside them, so we have to skip an iteration + before applying them to the type. If the declarator just + inside is the declarator-id, we apply the attrs to the + decl itself. */ + inner_attrs = TREE_PURPOSE (declarator); + ignore_attrs = 1; + declarator = TREE_VALUE (declarator); + } + break; + + case ARRAY_REF: + { + register tree itype = NULL_TREE; + register tree size = TREE_OPERAND (declarator, 1); + /* The index is a signed object `sizetype' bits wide. */ + tree index_type = signed_type (sizetype); + + declarator = TREE_OPERAND (declarator, 0); + + /* Check for some types that there cannot be arrays of. */ + + if (TREE_CODE (type) == VOID_TYPE) + { + cp_error ("declaration of `%D' as array of voids", dname); + type = error_mark_node; + } + + if (TREE_CODE (type) == FUNCTION_TYPE) + { + cp_error ("declaration of `%D' as array of functions", dname); + type = error_mark_node; + } + + /* ARM $8.4.3: Since you can't have a pointer to a reference, + you can't have arrays of references. If we allowed them, + then we'd be saying x[i] is valid for an array x, but + then you'd have to ask: what does `*(x + i)' mean? */ + if (TREE_CODE (type) == REFERENCE_TYPE) + { + if (decl_context == TYPENAME) + cp_error ("cannot make arrays of references"); + else + cp_error ("declaration of `%D' as array of references", + dname); + type = error_mark_node; + } + + if (TREE_CODE (type) == OFFSET_TYPE) + { + cp_error ("declaration of `%D' as array of data members", + dname); + type = error_mark_node; + } + + if (TREE_CODE (type) == METHOD_TYPE) + { + cp_error ("declaration of `%D' as array of function members", + dname); + type = error_mark_node; + } + + if (size == error_mark_node) + type = error_mark_node; + else if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)) + { + /* [dcl.array] + + the constant expressions that specify the bounds of + the arrays can be omitted only for the first member + of the sequence. */ + cp_error ("declaration of `%D' as multidimensional array", + dname); + cp_error ("must have bounds for all dimensions except the first"); + type = error_mark_node; + } + + if (type == error_mark_node) + continue; + + /* VC++ spells a zero-sized array with []. */ + if (size == NULL_TREE && decl_context == FIELD && ! staticp + && ! RIDBIT_SETP (RID_TYPEDEF, specbits)) + size = integer_zero_node; + + if (size) + { + /* Must suspend_momentary here because the index + type may need to live until the end of the function. + For example, it is used in the declaration of a + variable which requires destructing at the end of + the function; then build_vec_delete will need this + value. */ + int yes = suspend_momentary (); + /* Might be a cast. */ + if (TREE_CODE (size) == NOP_EXPR + && TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0))) + size = TREE_OPERAND (size, 0); + + /* If this involves a template parameter, it will be a + constant at instantiation time, but we don't know + what the value is yet. Even if no template + parameters are involved, we may an expression that + is not a constant; we don't even simplify `1 + 2' + when processing a template. */ + if (processing_template_decl) + { + /* Resolve a qualified reference to an enumerator or + static const data member of ours. */ + if (TREE_CODE (size) == SCOPE_REF + && TREE_OPERAND (size, 0) == current_class_type) + { + tree t = lookup_field (current_class_type, + TREE_OPERAND (size, 1), 0, 0); + if (t) + size = t; + } + + itype = build_index_type (build_min + (MINUS_EXPR, sizetype, size, integer_one_node)); + goto dont_grok_size; + } + + if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE + && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE + && TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE) + { + cp_error ("size of array `%D' has non-integer type", + dname); + size = integer_one_node; + } + if (TREE_READONLY_DECL_P (size)) + size = decl_constant_value (size); + if (pedantic && integer_zerop (size)) + cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", dname); + if (TREE_CONSTANT (size)) + { + int old_flag_pedantic_errors = flag_pedantic_errors; + int old_pedantic = pedantic; + pedantic = flag_pedantic_errors = 1; + /* Always give overflow errors on array subscripts. */ + constant_expression_warning (size); + pedantic = old_pedantic; + flag_pedantic_errors = old_flag_pedantic_errors; + if (INT_CST_LT (size, integer_zero_node)) + { + cp_error ("size of array `%D' is negative", dname); + size = integer_one_node; + } + } + else + { + if (pedantic) + { + if (dname) + cp_pedwarn ("ANSI C++ forbids variable-size array `%D'", + dname); + else + cp_pedwarn ("ANSI C++ forbids variable-size array"); + } + } + + itype + = fold (build_binary_op (MINUS_EXPR, + cp_convert (index_type, size), + cp_convert (index_type, + integer_one_node))); + if (! TREE_CONSTANT (itype)) + itype = variable_size (itype); + else if (TREE_OVERFLOW (itype)) + { + error ("overflow in array dimension"); + TREE_OVERFLOW (itype) = 0; + } + + /* If we're a parm, we need to have a permanent type so + mangling checks for re-use will work right. If both the + element and index types are permanent, the array type + will be, too. */ + if (decl_context == PARM + && allocation_temporary_p () && TREE_PERMANENT (type)) + { + push_obstacks (&permanent_obstack, &permanent_obstack); + itype = build_index_type (itype); + pop_obstacks (); + } + else + itype = build_index_type (itype); + + dont_grok_size: + resume_momentary (yes); + } + + type = build_cplus_array_type (type, itype); + ctype = NULL_TREE; + } + break; + + case CALL_EXPR: + { + tree arg_types; + int funcdecl_p; + tree inner_parms = TREE_OPERAND (declarator, 1); + tree inner_decl = TREE_OPERAND (declarator, 0); + + /* Declaring a function type. + Make sure we have a valid type for the function to return. */ + + /* We now know that the TYPE_QUALS don't apply to the + decl, but to its return type. */ + type_quals = TYPE_UNQUALIFIED; + + /* Warn about some types functions can't return. */ + + if (TREE_CODE (type) == FUNCTION_TYPE) + { + error ("`%s' declared as function returning a function", name); + type = integer_type_node; + } + if (TREE_CODE (type) == ARRAY_TYPE) + { + error ("`%s' declared as function returning an array", name); + type = integer_type_node; + } + + if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF) + inner_decl = TREE_OPERAND (inner_decl, 1); + + if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR) + inner_decl = dname; + + /* Pick up type qualifiers which should be applied to `this'. */ + quals = TREE_OPERAND (declarator, 2); + + /* Pick up the exception specifications. */ + raises = TREE_TYPE (declarator); + + /* Say it's a definition only for the CALL_EXPR + closest to the identifier. */ + funcdecl_p + = inner_decl + && (TREE_CODE (inner_decl) == IDENTIFIER_NODE + || TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR + || TREE_CODE (inner_decl) == BIT_NOT_EXPR); + + if (ctype == NULL_TREE + && decl_context == FIELD + && funcdecl_p + && (friendp == 0 || dname == current_class_name)) + ctype = current_class_type; + + if (ctype && return_type == return_conversion) + TYPE_HAS_CONVERSION (ctype) = 1; + if (ctype && constructor_name (ctype) == dname) + { + /* We are within a class's scope. If our declarator name + is the same as the class name, and we are defining + a function, then it is a constructor/destructor, and + therefore returns a void type. */ + + if (flags == DTOR_FLAG) + { + /* ANSI C++ June 5 1992 WP 12.4.1. A destructor may + not be declared const or volatile. A destructor + may not be static. */ + if (staticp == 2) + error ("destructor cannot be static member function"); + if (quals) + { + cp_error ("destructors may not be `%s'", + IDENTIFIER_POINTER (TREE_VALUE (quals))); + quals = NULL_TREE; + } + if (decl_context == FIELD) + { + if (! member_function_or_else (ctype, current_class_type, + "destructor for alien class `%s' cannot be a member")) + return void_type_node; + } + } + else /* It's a constructor. */ + { + if (explicitp == 1) + explicitp = 2; + /* ANSI C++ June 5 1992 WP 12.1.2. A constructor may + not be declared const or volatile. A constructor may + not be virtual. A constructor may not be static. */ + if (staticp == 2) + error ("constructor cannot be static member function"); + if (virtualp) + { + pedwarn ("constructors cannot be declared virtual"); + virtualp = 0; + } + if (quals) + { + cp_error ("constructors may not be `%s'", + IDENTIFIER_POINTER (TREE_VALUE (quals))); + quals = NULL_TREE; + } + { + RID_BIT_TYPE tmp_bits; + bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof (RID_BIT_TYPE)); + RIDBIT_RESET (RID_INLINE, tmp_bits); + RIDBIT_RESET (RID_STATIC, tmp_bits); + if (RIDBIT_ANY_SET (tmp_bits)) + error ("return value type specifier for constructor ignored"); + } + type = build_pointer_type (ctype); + if (decl_context == FIELD + && IS_SIGNATURE (current_class_type)) + { + error ("constructor not allowed in signature"); + return void_type_node; + } + else if (decl_context == FIELD) + { + if (! member_function_or_else (ctype, current_class_type, + "constructor for alien class `%s' cannot be member")) + return void_type_node; + TYPE_HAS_CONSTRUCTOR (ctype) = 1; + if (return_type != return_ctor) + return NULL_TREE; + } + } + if (decl_context == FIELD) + staticp = 0; + } + else if (friendp) + { + if (initialized) + error ("can't initialize friend function `%s'", name); + if (virtualp) + { + /* Cannot be both friend and virtual. */ + error ("virtual functions cannot be friends"); + RIDBIT_RESET (RID_FRIEND, specbits); + friendp = 0; + } + if (decl_context == NORMAL) + error ("friend declaration not in class definition"); + if (current_function_decl && funcdef_flag) + cp_error ("can't define friend function `%s' in a local class definition", + name); + } + + /* Construct the function type and go to the next + inner layer of declarator. */ + + declarator = TREE_OPERAND (declarator, 0); + + /* FIXME: This is where default args should be fully + processed. */ + + arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0); + + if (declarator && flags == DTOR_FLAG) + { + /* A destructor declared in the body of a class will + be represented as a BIT_NOT_EXPR. But, we just + want the underlying IDENTIFIER. */ + if (TREE_CODE (declarator) == BIT_NOT_EXPR) + declarator = TREE_OPERAND (declarator, 0); + + if (strict_prototype == 0 && arg_types == NULL_TREE) + arg_types = void_list_node; + else if (arg_types == NULL_TREE + || arg_types != void_list_node) + { + cp_error ("destructors may not have parameters"); + arg_types = void_list_node; + last_function_parms = NULL_TREE; + } + } + + /* ANSI says that `const int foo ();' + does not make the function foo const. */ + type = build_function_type (type, arg_types); + + { + tree t; + for (t = arg_types; t; t = TREE_CHAIN (t)) + if (TREE_PURPOSE (t) + && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG) + { + add_defarg_fn (type); + break; + } + } + } + break; + + case ADDR_EXPR: + case INDIRECT_REF: + /* Filter out pointers-to-references and references-to-references. + We can get these if a TYPE_DECL is used. */ + + if (TREE_CODE (type) == REFERENCE_TYPE) + { + error ("cannot declare %s to references", + TREE_CODE (declarator) == ADDR_EXPR + ? "references" : "pointers"); + declarator = TREE_OPERAND (declarator, 0); + continue; + } + + if (TREE_CODE (type) == OFFSET_TYPE + && (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE + || TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE)) + { + cp_error ("cannot declare pointer to `%#T' member", + TREE_TYPE (type)); + type = TREE_TYPE (type); + } + + /* Merge any constancy or volatility into the target type + for the pointer. */ + + /* We now know that the TYPE_QUALS don't apply to the decl, + but to the target of the pointer. */ + type_quals = TYPE_UNQUALIFIED; + + if (IS_SIGNATURE (type)) + { + if (TREE_CODE (declarator) == ADDR_EXPR) + { + if (CLASSTYPE_METHOD_VEC (type) == NULL_TREE + && TYPE_SIZE (type)) + cp_warning ("empty signature `%T' used in signature reference declaration", + type); +#if 0 + type = build_signature_reference_type (type); +#else + sorry ("signature reference"); + return NULL_TREE; +#endif + } + else + { + if (CLASSTYPE_METHOD_VEC (type) == NULL_TREE + && TYPE_SIZE (type)) + cp_warning ("empty signature `%T' used in signature pointer declaration", + type); + type = build_signature_pointer_type (type); + } + } + else if (TREE_CODE (declarator) == ADDR_EXPR) + { + if (TREE_CODE (type) == VOID_TYPE) + error ("invalid type: `void &'"); + else + type = build_reference_type (type); + } + else if (TREE_CODE (type) == METHOD_TYPE) + type = build_ptrmemfunc_type (build_pointer_type (type)); + else + type = build_pointer_type (type); + + /* Process a list of type modifier keywords (such as + const or volatile) that were given inside the `*' or `&'. */ + + if (TREE_TYPE (declarator)) + { + register tree typemodlist; + int erred = 0; + + constp = 0; + volatilep = 0; + restrictp = 0; + for (typemodlist = TREE_TYPE (declarator); typemodlist; + typemodlist = TREE_CHAIN (typemodlist)) + { + tree qualifier = TREE_VALUE (typemodlist); + + if (qualifier == ridpointers[(int) RID_CONST]) + constp++; + else if (qualifier == ridpointers[(int) RID_VOLATILE]) + volatilep++; + else if (qualifier == ridpointers[(int) RID_RESTRICT]) + restrictp++; + else if (!erred) + { + erred = 1; + error ("invalid type modifier within pointer declarator"); + } + } + if (constp > 1) + pedwarn ("duplicate `const'"); + if (volatilep > 1) + pedwarn ("duplicate `volatile'"); + if (restrictp > 1) + pedwarn ("duplicate `restrict'"); + + type_quals = ((constp ? TYPE_QUAL_CONST : 0) + | (restrictp ? TYPE_QUAL_RESTRICT : 0) + | (volatilep ? TYPE_QUAL_VOLATILE : 0)); + if (TREE_CODE (declarator) == ADDR_EXPR + && (constp || volatilep)) + { + if (constp) + pedwarn ("discarding `const' applied to a reference"); + if (volatilep) + pedwarn ("discarding `volatile' applied to a reference"); + type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); + } + type = cp_build_qualified_type (type, type_quals); + } + declarator = TREE_OPERAND (declarator, 0); + ctype = NULL_TREE; + break; + + case SCOPE_REF: + { + /* We have converted type names to NULL_TREE if the + name was bogus, or to a _TYPE node, if not. + + The variable CTYPE holds the type we will ultimately + resolve to. The code here just needs to build + up appropriate member types. */ + tree sname = TREE_OPERAND (declarator, 1); + tree t; + + /* Destructors can have their visibilities changed as well. */ + if (TREE_CODE (sname) == BIT_NOT_EXPR) + sname = TREE_OPERAND (sname, 0); + + if (TREE_COMPLEXITY (declarator) == 0) + /* This needs to be here, in case we are called + multiple times. */ ; + else if (TREE_COMPLEXITY (declarator) == -1) + /* Namespace member. */ + pop_decl_namespace (); + else if (friendp && (TREE_COMPLEXITY (declarator) < 2)) + /* Don't fall out into global scope. Hides real bug? --eichin */ ; + else if (! IS_AGGR_TYPE_CODE + (TREE_CODE (TREE_OPERAND (declarator, 0)))) + ; + else if (TREE_COMPLEXITY (declarator) == current_class_depth) + { + /* Resolve any TYPENAME_TYPEs from the decl-specifier-seq + that refer to ctype. They couldn't be resolved earlier + because we hadn't pushed into the class yet. + Example: resolve 'B::type' in + 'B::type> B::f () { }'. */ + if (current_template_parms + && uses_template_parms (type) + && uses_template_parms (current_class_type)) + { + tree args = current_template_args (); + type = tsubst (type, args, /*complain=*/1, NULL_TREE); + } + + /* This pop_nested_class corresponds to the + push_nested_class used to push into class scope for + parsing the argument list of a function decl, in + qualified_id. */ + pop_nested_class (); + TREE_COMPLEXITY (declarator) = current_class_depth; + } + else + my_friendly_abort (16); + + if (TREE_OPERAND (declarator, 0) == NULL_TREE) + { + /* We had a reference to a global decl, or + perhaps we were given a non-aggregate typedef, + in which case we cleared this out, and should just + keep going as though it wasn't there. */ + declarator = sname; + continue; + } + ctype = TREE_OPERAND (declarator, 0); + + t = ctype; + while (t != NULL_TREE && CLASS_TYPE_P (t)) + { + if (CLASSTYPE_TEMPLATE_INFO (t) && + !CLASSTYPE_TEMPLATE_SPECIALIZATION (t)) + template_count += 1; + t = TYPE_MAIN_DECL (t); + if (DECL_LANG_SPECIFIC (t)) + t = DECL_CLASS_CONTEXT (t); + else + t = NULL_TREE; + } + + if (sname == NULL_TREE) + goto done_scoping; + + if (TREE_CODE (sname) == IDENTIFIER_NODE) + { + /* This is the `standard' use of the scoping operator: + basetype :: member . */ + + if (ctype == current_class_type) + { + /* class A { + void A::f (); + }; + + Is this ill-formed? */ + + if (pedantic) + cp_pedwarn ("extra qualification `%T::' on member `%s' ignored", + ctype, name); + } + else if (TREE_CODE (type) == FUNCTION_TYPE) + { + if (current_class_type == NULL_TREE + || friendp) + type = build_cplus_method_type (ctype, TREE_TYPE (type), + TYPE_ARG_TYPES (type)); + else + { + cp_error ("cannot declare member function `%T::%s' within `%T'", + ctype, name, current_class_type); + return void_type_node; + } + } + else if (RIDBIT_SETP (RID_TYPEDEF, specbits) + || TYPE_SIZE (complete_type (ctype)) != NULL_TREE) + { + /* Have to move this code elsewhere in this function. + this code is used for i.e., typedef int A::M; M *pm; + + It is? How? jason 10/2/94 */ + + if (current_class_type) + { + cp_error ("cannot declare member `%T::%s' within `%T'", + ctype, name, current_class_type); + return void_type_node; + } + type = build_offset_type (ctype, type); + } + else if (uses_template_parms (ctype)) + { + if (TREE_CODE (type) == FUNCTION_TYPE) + type + = build_cplus_method_type (ctype, TREE_TYPE (type), + TYPE_ARG_TYPES (type)); + } + else + { + cp_error ("structure `%T' not yet defined", ctype); + return error_mark_node; + } + + declarator = sname; + } + else if (TREE_CODE (sname) == SCOPE_REF) + my_friendly_abort (17); + else + { + done_scoping: + declarator = TREE_OPERAND (declarator, 1); + if (declarator && TREE_CODE (declarator) == CALL_EXPR) + /* In this case, we will deal with it later. */ + ; + else + { + if (TREE_CODE (type) == FUNCTION_TYPE) + type = build_cplus_method_type (ctype, TREE_TYPE (type), + TYPE_ARG_TYPES (type)); + else + type = build_offset_type (ctype, type); + } + } + } + break; + + case BIT_NOT_EXPR: + declarator = TREE_OPERAND (declarator, 0); + break; + + case RECORD_TYPE: + case UNION_TYPE: + case ENUMERAL_TYPE: + declarator = NULL_TREE; + break; + + case ERROR_MARK: + declarator = NULL_TREE; + break; + + default: + my_friendly_abort (158); + } + } + + /* See the comment for the TREE_LIST case, above. */ + if (inner_attrs) + { + if (! ignore_attrs) + decl_attributes (type, inner_attrs, NULL_TREE); + else if (attrlist) + TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist)); + else + attrlist = build_decl_list (NULL_TREE, inner_attrs); + } + + /* Now TYPE has the actual type. */ + + if (explicitp == 1) + { + error ("only constructors can be declared `explicit'"); + explicitp = 0; + } + + if (RIDBIT_SETP (RID_MUTABLE, specbits)) + { + if (type_quals & TYPE_QUAL_CONST) + { + error ("const `%s' cannot be declared `mutable'", name); + RIDBIT_RESET (RID_MUTABLE, specbits); + } + else if (staticp) + { + error ("static `%s' cannot be declared `mutable'", name); + RIDBIT_RESET (RID_MUTABLE, specbits); + } + } + + if (declarator == NULL_TREE + || TREE_CODE (declarator) == IDENTIFIER_NODE + || (TREE_CODE (declarator) == TEMPLATE_ID_EXPR + && (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE))) + /* OK */; + else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) + { + cp_error ("template-id `%D' used as a declarator", declarator); + declarator = dname; + } + else + /* Unexpected declarator format. */ + my_friendly_abort (990210); + + /* If this is declaring a typedef name, return a TYPE_DECL. */ + + if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME) + { + tree decl; + + /* Note that the grammar rejects storage classes + in typenames, fields or parameters. */ + if (current_lang_name == lang_name_java) + TYPE_FOR_JAVA (type) = 1; + + if (decl_context == FIELD) + { + if (declarator == constructor_name (current_class_type)) + cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class", + declarator); + decl = build_lang_decl (TYPE_DECL, declarator, type); + if (IS_SIGNATURE (current_class_type) && opaque_typedef) + SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1; + } + else + { + /* Make sure this typedef lives as long as its type, + since it might be used as a template parameter. */ + if (type != error_mark_node) + push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type)); + decl = build_decl (TYPE_DECL, declarator, type); + if (type != error_mark_node) + pop_obstacks (); + } + + /* If the user declares "struct {...} foo" then `foo' will have + an anonymous name. Fill that name in now. Nothing can + refer to it, so nothing needs know about the name change. + The TYPE_NAME field was filled in by build_struct_xref. */ + if (type != error_mark_node + && TYPE_NAME (type) + && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))) + { + tree oldname = TYPE_NAME (type); + tree t; + + /* FIXME: This is bogus; we should not be doing this for + cv-qualified types. */ + + /* Replace the anonymous name with the real name everywhere. */ + lookup_tag_reverse (type, declarator); + for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) + if (TYPE_NAME (t) == oldname) + TYPE_NAME (t) = decl; + + if (TYPE_LANG_SPECIFIC (type)) + TYPE_WAS_ANONYMOUS (type) = 1; + + /* If this is a typedef within a template class, the nested + type is a (non-primary) template. The name for the + template needs updating as well. */ + if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_TEMPLATE_INFO (type)) + DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)) + = TYPE_IDENTIFIER (type); + + /* XXX Temporarily set the scope. + When returning, start_decl expects it as NULL_TREE, + and will then then set it using pushdecl. */ + my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 980404); + if (current_class_type) + DECL_CONTEXT (decl) = current_class_type; + else + DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); + + DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl); + DECL_ASSEMBLER_NAME (decl) + = get_identifier (build_overload_name (type, 1, 1)); + DECL_CONTEXT (decl) = NULL_TREE; + + /* FIXME remangle member functions; member functions of a + type with external linkage have external linkage. */ + } + + if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE) + { + cp_error_at ("typedef name may not be class-qualified", decl); + return NULL_TREE; + } + else if (quals) + { + if (ctype == NULL_TREE) + { + if (TREE_CODE (type) != METHOD_TYPE) + cp_error_at ("invalid type qualifier for non-method type", decl); + else + ctype = TYPE_METHOD_BASETYPE (type); + } + if (ctype != NULL_TREE) + grok_method_quals (ctype, decl, quals); + } + + if (RIDBIT_SETP (RID_SIGNED, specbits) + || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) + C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; + + if (RIDBIT_SETP (RID_MUTABLE, specbits)) + error ("non-object member `%s' cannot be declared mutable", name); + + bad_specifiers (decl, "type", virtualp, quals != NULL_TREE, + inlinep, friendp, raises != NULL_TREE); + + if (initialized) + error ("typedef declaration includes an initializer"); + + return decl; + } + + /* Detect the case of an array type of unspecified size + which came, as such, direct from a typedef name. + We must copy the type, so that each identifier gets + a distinct type, so that each identifier's size can be + controlled separately by its own initializer. */ + + if (type == typedef_type && TREE_CODE (type) == ARRAY_TYPE + && TYPE_DOMAIN (type) == NULL_TREE) + { + type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type)); + } + + /* If this is a type name (such as, in a cast or sizeof), + compute the type and return it now. */ + + if (decl_context == TYPENAME) + { + /* Note that the grammar rejects storage classes + in typenames, fields or parameters. */ + if (type_quals != TYPE_UNQUALIFIED) + { + if (IS_SIGNATURE (type)) + error ("type qualifiers specified for signature type"); + type_quals = TYPE_UNQUALIFIED; + } + + /* Special case: "friend class foo" looks like a TYPENAME context. */ + if (friendp) + { + if (type_quals != TYPE_UNQUALIFIED) + { + cp_error ("type qualifiers specified for friend class declaration"); + type_quals = TYPE_UNQUALIFIED; + } + if (inlinep) + { + cp_error ("`inline' specified for friend class declaration"); + inlinep = 0; + } + + /* Only try to do this stuff if we didn't already give up. */ + if (type != integer_type_node) + { + /* A friendly class? */ + if (current_class_type) + make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type)); + else + error ("trying to make class `%s' a friend of global scope", + TYPE_NAME_STRING (type)); + type = void_type_node; + } + } + else if (quals) + { + tree dummy = build_decl (TYPE_DECL, declarator, type); + if (ctype == NULL_TREE) + { + my_friendly_assert (TREE_CODE (type) == METHOD_TYPE, 159); + ctype = TYPE_METHOD_BASETYPE (type); + } + grok_method_quals (ctype, dummy, quals); + type = TREE_TYPE (dummy); + } + + return type; + } + else if (declarator == NULL_TREE && decl_context != PARM + && decl_context != CATCHPARM + && TREE_CODE (type) != UNION_TYPE + && ! bitfield) + { + cp_error ("abstract declarator `%T' used as declaration", type); + declarator = make_anon_name (); + } + + /* `void' at top level (not within pointer) + is allowed only in typedefs or type names. + We don't complain about parms either, but that is because + a better error message can be made later. */ + + if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM) + { + if (! declarator) + error ("unnamed variable or field declared void"); + else if (TREE_CODE (declarator) == IDENTIFIER_NODE) + { + if (IDENTIFIER_OPNAME_P (declarator)) + my_friendly_abort (356); + else + error ("variable or field `%s' declared void", name); + } + else + error ("variable or field declared void"); + type = integer_type_node; + } + + /* Now create the decl, which may be a VAR_DECL, a PARM_DECL + or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */ + + if (decl_context == PARM || decl_context == CATCHPARM) + { + if (ctype || in_namespace) + error ("cannot use `::' in parameter declaration"); + + /* A parameter declared as an array of T is really a pointer to T. + One declared as a function is really a pointer to a function. + One declared as a member is really a pointer to member. */ + + if (TREE_CODE (type) == ARRAY_TYPE) + { + /* Transfer const-ness of array into that of type pointed to. */ + type = build_pointer_type (TREE_TYPE (type)); + type_quals = TYPE_UNQUALIFIED; + } + else if (TREE_CODE (type) == FUNCTION_TYPE) + type = build_pointer_type (type); + else if (TREE_CODE (type) == OFFSET_TYPE) + type = build_pointer_type (type); + else if (TREE_CODE (type) == VOID_TYPE && declarator) + { + error ("declaration of `%s' as void", name); + return NULL_TREE; + } + } + + { + register tree decl; + + if (decl_context == PARM) + { + decl = build_decl (PARM_DECL, declarator, type); + + bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE, + inlinep, friendp, raises != NULL_TREE); + if (current_class_type + && IS_SIGNATURE (current_class_type)) + { + if (inlinep) + error ("parameter of signature member function declared `inline'"); + if (RIDBIT_SETP (RID_AUTO, specbits)) + error ("parameter of signature member function declared `auto'"); + if (RIDBIT_SETP (RID_REGISTER, specbits)) + error ("parameter of signature member function declared `register'"); + } + + /* Compute the type actually passed in the parmlist, + for the case where there is no prototype. + (For example, shorts and chars are passed as ints.) + When there is a prototype, this is overridden later. */ + + DECL_ARG_TYPE (decl) = type_promotes_to (type); + } + else if (decl_context == FIELD) + { + if (type == error_mark_node) + { + /* Happens when declaring arrays of sizes which + are error_mark_node, for example. */ + decl = NULL_TREE; + } + else if (in_namespace && !friendp) + { + /* Something like struct S { int N::j; }; */ + cp_error ("invalid use of `::'"); + decl = NULL_TREE; + } + else if (TREE_CODE (type) == FUNCTION_TYPE) + { + int publicp = 0; + tree function_context; + + /* We catch the others as conflicts with the builtin + typedefs. */ + if (friendp && declarator == ridpointers[(int) RID_SIGNED]) + { + cp_error ("function `%D' cannot be declared friend", + declarator); + friendp = 0; + } + + if (friendp == 0) + { + if (ctype == NULL_TREE) + ctype = current_class_type; + + if (ctype == NULL_TREE) + { + cp_error ("can't make `%D' into a method -- not in a class", + declarator); + return void_type_node; + } + + /* ``A union may [ ... ] not [ have ] virtual functions.'' + ARM 9.5 */ + if (virtualp && TREE_CODE (ctype) == UNION_TYPE) + { + cp_error ("function `%D' declared virtual inside a union", + declarator); + return void_type_node; + } + + if (declarator == ansi_opname[(int) NEW_EXPR] + || declarator == ansi_opname[(int) VEC_NEW_EXPR] + || declarator == ansi_opname[(int) DELETE_EXPR] + || declarator == ansi_opname[(int) VEC_DELETE_EXPR]) + { + if (virtualp) + { + cp_error ("`%D' cannot be declared virtual, since it is always static", + declarator); + virtualp = 0; + } + } + else if (staticp < 2) + type = build_cplus_method_type (ctype, TREE_TYPE (type), + TYPE_ARG_TYPES (type)); + } + + /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ + function_context = (ctype != NULL_TREE) ? + hack_decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE; + publicp = (! friendp || ! staticp) + && function_context == NULL_TREE; + decl = grokfndecl (ctype, type, + TREE_CODE (declarator) != TEMPLATE_ID_EXPR + ? declarator : dname, + declarator, + virtualp, flags, quals, raises, + friendp ? -1 : 0, friendp, publicp, inlinep, + funcdef_flag, template_count, in_namespace); + if (decl == NULL_TREE) + return decl; +#if 0 + /* This clobbers the attrs stored in `decl' from `attrlist'. */ + /* The decl and setting of decl_machine_attr is also turned off. */ + decl = build_decl_attribute_variant (decl, decl_machine_attr); +#endif + + /* [class.conv.ctor] + + A constructor declared without the function-specifier + explicit that can be called with a single parameter + specifies a conversion from the type of its first + parameter to the type of its class. Such a constructor + is called a converting constructor. */ + if (explicitp == 2) + DECL_NONCONVERTING_P (decl) = 1; + else if (DECL_CONSTRUCTOR_P (decl)) + { + /* The constructor can be called with exactly one + parameter if there is at least one parameter, and + any subsequent parameters have default arguments. + We don't look at the first parameter, which is + really just the `this' parameter for the new + object. */ + tree arg_types = + TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))); + + /* Skip the `in_chrg' argument too, if present. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (decl))) + arg_types = TREE_CHAIN (arg_types); + + /* And the `vlist' argument. */ + if (TYPE_USES_PVBASES (DECL_CONTEXT (decl))) + arg_types = TREE_CHAIN (arg_types); + + if (arg_types == void_list_node + || (arg_types + && TREE_CHAIN (arg_types) + && TREE_CHAIN (arg_types) != void_list_node + && !TREE_PURPOSE (TREE_CHAIN (arg_types)))) + DECL_NONCONVERTING_P (decl) = 1; + } + } + else if (TREE_CODE (type) == METHOD_TYPE) + { + /* We only get here for friend declarations of + members of other classes. */ + /* All method decls are public, so tell grokfndecl to set + TREE_PUBLIC, also. */ + decl = grokfndecl (ctype, type, declarator, declarator, + virtualp, flags, quals, raises, + friendp ? -1 : 0, friendp, 1, 0, funcdef_flag, + template_count, in_namespace); + if (decl == NULL_TREE) + return NULL_TREE; + } + else if (!staticp && ! processing_template_decl + && TYPE_SIZE (complete_type (type)) == NULL_TREE + && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) + { + if (declarator) + cp_error ("field `%D' has incomplete type", declarator); + else + cp_error ("name `%T' has incomplete type", type); + + /* If we're instantiating a template, tell them which + instantiation made the field's type be incomplete. */ + if (current_class_type + && TYPE_NAME (current_class_type) + && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type)) + && declspecs && TREE_VALUE (declspecs) + && TREE_TYPE (TREE_VALUE (declspecs)) == type) + cp_error (" in instantiation of template `%T'", + current_class_type); + + type = error_mark_node; + decl = NULL_TREE; + } + else + { + if (friendp) + { + error ("`%s' is neither function nor method; cannot be declared friend", + IDENTIFIER_POINTER (declarator)); + friendp = 0; + } + decl = NULL_TREE; + } + + if (friendp) + { + /* Friends are treated specially. */ + if (ctype == current_class_type) + warning ("member functions are implicitly friends of their class"); + else + { + tree t = NULL_TREE; + if (decl && DECL_NAME (decl)) + { + if (template_class_depth (current_class_type) == 0) + { + decl + = check_explicit_specialization + (declarator, decl, + template_count, 2 * (funcdef_flag != 0) + 4); + if (decl == error_mark_node) + return error_mark_node; + } + + t = do_friend (ctype, declarator, decl, + last_function_parms, attrlist, flags, quals, + funcdef_flag); + } + if (t && funcdef_flag) + return t; + + return void_type_node; + } + } + + /* Structure field. It may not be a function, except for C++ */ + + if (decl == NULL_TREE) + { + if (initialized) + { + if (!staticp) + { + /* An attempt is being made to initialize a non-static + member. But, from [class.mem]: + + 4 A member-declarator can contain a + constant-initializer only if it declares a static + member (_class.static_) of integral or enumeration + type, see _class.static.data_. + + This used to be relatively common practice, but + the rest of the compiler does not correctly + handle the initialization unless the member is + static so we make it static below. */ + cp_pedwarn ("ANSI C++ forbids initialization of member `%D'", + declarator); + cp_pedwarn ("making `%D' static", declarator); + staticp = 1; + } + + if (uses_template_parms (type)) + /* We'll check at instantiation time. */ + ; + else if (check_static_variable_definition (declarator, + type)) + /* If we just return the declaration, crashes + will sometimes occur. We therefore return + void_type_node, as if this was a friend + declaration, to cause callers to completely + ignore this declaration. */ + return void_type_node; + } + + /* 9.2p13 [class.mem] */ + if (declarator == constructor_name (current_class_type) + /* Divergence from the standard: In extern "C", we + allow non-static data members here, because C does + and /usr/include/netinet/in.h uses that. */ + && (staticp || ! in_system_header)) + cp_pedwarn ("ANSI C++ forbids data member `%D' with same name as enclosing class", + declarator); + + if (staticp) + { + /* C++ allows static class members. + All other work for this is done by grokfield. + This VAR_DCL is built by build_lang_field_decl. + All other VAR_DECLs are built by build_decl. */ + decl = build_lang_field_decl (VAR_DECL, declarator, type); + TREE_STATIC (decl) = 1; + /* In class context, 'static' means public access. */ + TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1; + } + else + { + decl = build_lang_field_decl (FIELD_DECL, declarator, type); + if (RIDBIT_SETP (RID_MUTABLE, specbits)) + { + DECL_MUTABLE_P (decl) = 1; + RIDBIT_RESET (RID_MUTABLE, specbits); + } + } + + bad_specifiers (decl, "field", virtualp, quals != NULL_TREE, + inlinep, friendp, raises != NULL_TREE); + } + } + else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) + { + tree original_name; + int publicp = 0; + + if (! declarator) + return NULL_TREE; + + if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) + original_name = dname; + else + original_name = declarator; + + if (RIDBIT_SETP (RID_AUTO, specbits)) + error ("storage class `auto' invalid for function `%s'", name); + else if (RIDBIT_SETP (RID_REGISTER, specbits)) + error ("storage class `register' invalid for function `%s'", name); + + /* Function declaration not at top level. + Storage classes other than `extern' are not allowed + and `extern' makes no difference. */ + if (! toplevel_bindings_p () + && (RIDBIT_SETP (RID_STATIC, specbits) + || RIDBIT_SETP (RID_INLINE, specbits)) + && pedantic) + { + if (RIDBIT_SETP (RID_STATIC, specbits)) + pedwarn ("storage class `static' invalid for function `%s' declared out of global scope", name); + else + pedwarn ("storage class `inline' invalid for function `%s' declared out of global scope", name); + } + + if (ctype == NULL_TREE) + { + if (virtualp) + { + error ("virtual non-class function `%s'", name); + virtualp = 0; + } + } + else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2) + type = build_cplus_method_type (ctype, TREE_TYPE (type), + TYPE_ARG_TYPES (type)); + + /* Record presence of `static'. */ + publicp = (ctype != NULL_TREE + || RIDBIT_SETP (RID_EXTERN, specbits) + || !RIDBIT_SETP (RID_STATIC, specbits)); + + decl = grokfndecl (ctype, type, original_name, declarator, + virtualp, flags, quals, raises, + 1, friendp, + publicp, inlinep, funcdef_flag, + template_count, in_namespace); + if (decl == NULL_TREE) + return NULL_TREE; + + if (staticp == 1) + { + int illegal_static = 0; + + /* Don't allow a static member function in a class, and forbid + declaring main to be static. */ + if (TREE_CODE (type) == METHOD_TYPE) + { + cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl); + illegal_static = 1; + } + else if (current_function_decl) + { + /* FIXME need arm citation */ + error ("cannot declare static function inside another function"); + illegal_static = 1; + } + + if (illegal_static) + { + staticp = 0; + RIDBIT_RESET (RID_STATIC, specbits); + } + } + } + else + { + /* It's a variable. */ + + /* An uninitialized decl with `extern' is a reference. */ + decl = grokvardecl (type, declarator, &specbits, + initialized, + (type_quals & TYPE_QUAL_CONST) != 0, + in_namespace); + bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE, + inlinep, friendp, raises != NULL_TREE); + + if (ctype) + { + DECL_CONTEXT (decl) = ctype; + if (staticp == 1) + { + cp_pedwarn ("static member `%D' re-declared as static", decl); + staticp = 0; + RIDBIT_RESET (RID_STATIC, specbits); + } + if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl)) + { + cp_error ("static member `%D' declared `register'", decl); + RIDBIT_RESET (RID_REGISTER, specbits); + } + if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic) + { + cp_pedwarn ("cannot explicitly declare member `%#D' to have extern linkage", + decl); + RIDBIT_RESET (RID_EXTERN, specbits); + } + } + } + + if (RIDBIT_SETP (RID_MUTABLE, specbits)) + { + error ("`%s' cannot be declared mutable", name); + } + + /* Record `register' declaration for warnings on & + and in case doing stupid register allocation. */ + + if (RIDBIT_SETP (RID_REGISTER, specbits)) + DECL_REGISTER (decl) = 1; + + if (RIDBIT_SETP (RID_EXTERN, specbits)) + DECL_THIS_EXTERN (decl) = 1; + + if (RIDBIT_SETP (RID_STATIC, specbits)) + DECL_THIS_STATIC (decl) = 1; + + /* Record constancy and volatility. */ + /* FIXME: Disallow `restrict' pointer-to-member declarations. */ + c_apply_type_quals_to_decl (type_quals, decl); + + return decl; + } +} + +/* Tell if a parmlist/exprlist looks like an exprlist or a parmlist. + An empty exprlist is a parmlist. An exprlist which + contains only identifiers at the global level + is a parmlist. Otherwise, it is an exprlist. */ + +int +parmlist_is_exprlist (exprs) + tree exprs; +{ + if (exprs == NULL_TREE || TREE_PARMLIST (exprs)) + return 0; + + if (toplevel_bindings_p ()) + { + /* At the global level, if these are all identifiers, + then it is a parmlist. */ + while (exprs) + { + if (TREE_CODE (TREE_VALUE (exprs)) != IDENTIFIER_NODE) + return 1; + exprs = TREE_CHAIN (exprs); + } + return 0; + } + return 1; +} + +/* Subroutine of start_function. Ensure that each of the parameter + types (as listed in PARMS) is complete, as is required for a + function definition. */ + +static void +require_complete_types_for_parms (parms) + tree parms; +{ + while (parms) + { + tree type = TREE_TYPE (parms); + if (TYPE_SIZE (complete_type (type)) == NULL_TREE) + { + if (DECL_NAME (parms)) + error ("parameter `%s' has incomplete type", + IDENTIFIER_POINTER (DECL_NAME (parms))); + else + error ("parameter has incomplete type"); + TREE_TYPE (parms) = error_mark_node; + } + else + layout_decl (parms, 0); + + parms = TREE_CHAIN (parms); + } +} + +/* Returns DECL if DECL is a local variable (or parameter). Returns + NULL_TREE otherwise. */ + +static tree +local_variable_p (t) + tree t; +{ + if ((TREE_CODE (t) == VAR_DECL + /* A VAR_DECL with a context that is a _TYPE is a static data + member. */ + && !TYPE_P (CP_DECL_CONTEXT (t)) + /* Any other non-local variable must be at namespace scope. */ + && TREE_CODE (CP_DECL_CONTEXT (t)) != NAMESPACE_DECL) + || (TREE_CODE (t) == PARM_DECL)) + return t; + + return NULL_TREE; +} + +/* Check that ARG, which is a default-argument expression for a + parameter DECL, is legal. Returns ARG, or ERROR_MARK_NODE, if + something goes wrong. DECL may also be a _TYPE node, rather than a + DECL, if there is no DECL available. */ + +tree +check_default_argument (decl, arg) + tree decl; + tree arg; +{ + tree var; + tree decl_type; + + if (TREE_CODE (arg) == DEFAULT_ARG) + /* We get a DEFAULT_ARG when looking at an in-class declaration + with a default argument. Ignore the argument for now; we'll + deal with it after the class is complete. */ + return arg; + + if (processing_template_decl || uses_template_parms (arg)) + /* We don't do anything checking until instantiation-time. Note + that there may be uninstantiated arguments even for an + instantiated function, since default arguments are not + instantiated until they are needed. */ + return arg; + + if (TYPE_P (decl)) + { + decl_type = decl; + decl = NULL_TREE; + } + else + decl_type = TREE_TYPE (decl); + + if (arg == error_mark_node + || decl == error_mark_node + || TREE_TYPE (arg) == error_mark_node + || decl_type == error_mark_node) + /* Something already went wrong. There's no need to check + further. */ + return error_mark_node; + + /* [dcl.fct.default] + + A default argument expression is implicitly converted to the + parameter type. */ + if (!TREE_TYPE (arg) + || !can_convert_arg (decl_type, TREE_TYPE (arg), arg)) + { + if (decl) + cp_error ("default argument for `%#D' has type `%T'", + decl, TREE_TYPE (arg)); + else + cp_error ("default argument for paramter of type `%T' has type `%T'", + decl_type, TREE_TYPE (arg)); + + return error_mark_node; + } + + /* [dcl.fct.default] + + Local variables shall not be used in default argument + expressions. + + The keyword `this' shall not be used in a default argument of a + member function. */ + var = search_tree (arg, local_variable_p); + if (var) + { + cp_error ("default argument `%E' uses local variable `%D'", + arg, var); + return error_mark_node; + } + + /* All is well. */ + return arg; +} + +/* Decode the list of parameter types for a function type. + Given the list of things declared inside the parens, + return a list of types. + + The list we receive can have three kinds of elements: + an IDENTIFIER_NODE for names given without types, + a TREE_LIST node for arguments given as typespecs or names with typespecs, + or void_type_node, to mark the end of an argument list + when additional arguments are not permitted (... was not used). + + FUNCDEF_FLAG is nonzero for a function definition, 0 for + a mere declaration. A nonempty identifier-list gets an error message + when FUNCDEF_FLAG is zero. + If FUNCDEF_FLAG is 1, then parameter types must be complete. + If FUNCDEF_FLAG is -1, then parameter types may be incomplete. + + If all elements of the input list contain types, + we return a list of the types. + If all elements contain no type (except perhaps a void_type_node + at the end), we return a null list. + If some have types and some do not, it is an error, and we + return a null list. + + Also set last_function_parms to either + a list of names (IDENTIFIER_NODEs) or a chain of PARM_DECLs. + A list of names is converted to a chain of PARM_DECLs + by store_parm_decls so that ultimately it is always a chain of decls. + + Note that in C++, parameters can take default values. These default + values are in the TREE_PURPOSE field of the TREE_LIST. It is + an error to specify default values which are followed by parameters + that have no default values, or an ELLIPSES. For simplicities sake, + only parameters which are specified with their types can take on + default values. */ + +static tree +grokparms (first_parm, funcdef_flag) + tree first_parm; + int funcdef_flag; +{ + tree result = NULL_TREE; + tree decls = NULL_TREE; + + if (first_parm != NULL_TREE + && TREE_CODE (TREE_VALUE (first_parm)) == IDENTIFIER_NODE) + { + if (! funcdef_flag) + pedwarn ("parameter names (without types) in function declaration"); + last_function_parms = first_parm; + return NULL_TREE; + } + else if (first_parm != NULL_TREE + && TREE_CODE (TREE_VALUE (first_parm)) != TREE_LIST + && TREE_CODE (TREE_VALUE (first_parm)) != VOID_TYPE) + my_friendly_abort (145); + else + { + /* Types were specified. This is a list of declarators + each represented as a TREE_LIST node. */ + register tree parm, chain; + int any_init = 0, any_error = 0; + + if (first_parm != NULL_TREE) + { + tree last_result = NULL_TREE; + tree last_decl = NULL_TREE; + + for (parm = first_parm; parm != NULL_TREE; parm = chain) + { + tree type = NULL_TREE, list_node = parm; + register tree decl = TREE_VALUE (parm); + tree init = TREE_PURPOSE (parm); + + chain = TREE_CHAIN (parm); + /* @@ weak defense against parse errors. */ + if (TREE_CODE (decl) != VOID_TYPE + && TREE_CODE (decl) != TREE_LIST) + { + /* Give various messages as the need arises. */ + if (TREE_CODE (decl) == STRING_CST) + cp_error ("invalid string constant `%E'", decl); + else if (TREE_CODE (decl) == INTEGER_CST) + error ("invalid integer constant in parameter list, did you forget to give parameter name?"); + continue; + } + + if (TREE_CODE (decl) != VOID_TYPE) + { + decl = grokdeclarator (TREE_VALUE (decl), + TREE_PURPOSE (decl), + PARM, init != NULL_TREE, + NULL_TREE); + if (! decl || TREE_TYPE (decl) == error_mark_node) + continue; + + /* Top-level qualifiers on the parameters are + ignored for function types. */ + type = TYPE_MAIN_VARIANT (TREE_TYPE (decl)); + + if (TREE_CODE (type) == VOID_TYPE) + decl = void_type_node; + else if (TREE_CODE (type) == METHOD_TYPE) + { + if (DECL_NAME (decl)) + /* Cannot use the decl here because + we don't have DECL_CONTEXT set up yet. */ + cp_error ("parameter `%D' invalidly declared method type", + DECL_NAME (decl)); + else + error ("parameter invalidly declared method type"); + type = build_pointer_type (type); + TREE_TYPE (decl) = type; + } + else if (TREE_CODE (type) == OFFSET_TYPE) + { + if (DECL_NAME (decl)) + cp_error ("parameter `%D' invalidly declared offset type", + DECL_NAME (decl)); + else + error ("parameter invalidly declared offset type"); + type = build_pointer_type (type); + TREE_TYPE (decl) = type; + } + else if (TREE_CODE (type) == RECORD_TYPE + && TYPE_LANG_SPECIFIC (type) + && CLASSTYPE_ABSTRACT_VIRTUALS (type)) + { + abstract_virtuals_error (decl, type); + any_error = 1; /* Seems like a good idea. */ + } + else if (TREE_CODE (type) == RECORD_TYPE + && TYPE_LANG_SPECIFIC (type) + && IS_SIGNATURE (type)) + { + signature_error (decl, type); + any_error = 1; /* Seems like a good idea. */ + } + else if (POINTER_TYPE_P (type)) + { + tree t = type; + while (POINTER_TYPE_P (t) + || (TREE_CODE (t) == ARRAY_TYPE + && TYPE_DOMAIN (t) != NULL_TREE)) + t = TREE_TYPE (t); + if (TREE_CODE (t) == ARRAY_TYPE) + cp_error ("parameter type `%T' includes %s to array of unknown bound", + type, + TYPE_PTR_P (type) ? "pointer" : "reference"); + } + } + + if (TREE_CODE (decl) == VOID_TYPE) + { + if (result == NULL_TREE) + { + result = void_list_node; + last_result = result; + } + else + { + TREE_CHAIN (last_result) = void_list_node; + last_result = void_list_node; + } + if (chain + && (chain != void_list_node || TREE_CHAIN (chain))) + error ("`void' in parameter list must be entire list"); + break; + } + + /* Since there is a prototype, args are passed in their own types. */ + DECL_ARG_TYPE (decl) = TREE_TYPE (decl); +#ifdef PROMOTE_PROTOTYPES + if ((TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) + DECL_ARG_TYPE (decl) = integer_type_node; +#endif + if (!any_error && init) + { + any_init++; + init = check_default_argument (decl, init); + } + else + init = NULL_TREE; + + if (decls == NULL_TREE) + { + decls = decl; + last_decl = decls; + } + else + { + TREE_CHAIN (last_decl) = decl; + last_decl = decl; + } + if (! current_function_decl && TREE_PERMANENT (list_node)) + { + TREE_PURPOSE (list_node) = init; + TREE_VALUE (list_node) = type; + TREE_CHAIN (list_node) = NULL_TREE; + } + else + list_node = saveable_tree_cons (init, type, NULL_TREE); + if (result == NULL_TREE) + { + result = list_node; + last_result = result; + } + else + { + TREE_CHAIN (last_result) = list_node; + last_result = list_node; + } + } + if (last_result) + TREE_CHAIN (last_result) = NULL_TREE; + /* If there are no parameters, and the function does not end + with `...', then last_decl will be NULL_TREE. */ + if (last_decl != NULL_TREE) + TREE_CHAIN (last_decl) = NULL_TREE; + } + } + + last_function_parms = decls; + + return result; +} + +/* Called from the parser to update an element of TYPE_ARG_TYPES for some + FUNCTION_TYPE with the newly parsed version of its default argument, which + was previously digested as text. See snarf_defarg et al in lex.c. */ + +void +replace_defarg (arg, init) + tree arg, init; +{ + if (! processing_template_decl + && ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init)) + cp_pedwarn ("invalid type `%T' for default argument to `%T'", + TREE_TYPE (init), TREE_VALUE (arg)); + TREE_PURPOSE (arg) = init; +} + +/* Return 1 if D copies its arguments. This is used to test for copy + constructors and copy assignment operators. */ + +int +copy_args_p (d) + tree d; +{ + tree t = FUNCTION_ARG_CHAIN (d); + if (DECL_CONSTRUCTOR_P (d) + && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (d))) + { + t = TREE_CHAIN (t); + if (TYPE_USES_PVBASES (DECL_CONTEXT (d))) + t = TREE_CHAIN (t); + } + + if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE + && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t))) + == DECL_CLASS_CONTEXT (d)) + && (TREE_CHAIN (t) == NULL_TREE + || TREE_CHAIN (t) == void_list_node + || TREE_PURPOSE (TREE_CHAIN (t)))) + return 1; + return 0; +} + +/* These memoizing functions keep track of special properties which + a class may have. `grok_ctor_properties' notices whether a class + has a constructor of the form X(X&), and also complains + if the class has a constructor of the form X(X). + `grok_op_properties' takes notice of the various forms of + operator= which are defined, as well as what sorts of type conversion + may apply. Both functions take a FUNCTION_DECL as an argument. */ + +int +grok_ctor_properties (ctype, decl) + tree ctype, decl; +{ + tree parmtypes = FUNCTION_ARG_CHAIN (decl); + tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node; + + /* When a type has virtual baseclasses, a magical first int argument is + added to any ctor so we can tell if the class has been initialized + yet. This could screw things up in this function, so we deliberately + ignore the leading int if we're in that situation. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (ctype) + && !CLASSTYPE_IS_TEMPLATE (ctype)) + { + my_friendly_assert (parmtypes + && TREE_VALUE (parmtypes) == integer_type_node, + 980529); + parmtypes = TREE_CHAIN (parmtypes); + parmtype = TREE_VALUE (parmtypes); + } + + if (TYPE_USES_PVBASES (ctype)) + { + my_friendly_assert (parmtypes + && TREE_VALUE (parmtypes) == vlist_type_node, + 980529); + parmtypes = TREE_CHAIN (parmtypes); + parmtype = TREE_VALUE (parmtypes); + } + + /* [class.copy] + + A non-template constructor for class X is a copy constructor if + its first parameter is of type X&, const X&, volatile X& or const + volatile X&, and either there are no other parameters or else all + other parameters have default arguments. */ + if (TREE_CODE (parmtype) == REFERENCE_TYPE + && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype + && (TREE_CHAIN (parmtypes) == NULL_TREE + || TREE_CHAIN (parmtypes) == void_list_node + || TREE_PURPOSE (TREE_CHAIN (parmtypes))) + && !(DECL_TEMPLATE_INSTANTIATION (decl) + && is_member_template (DECL_TI_TEMPLATE (decl)))) + { + TYPE_HAS_INIT_REF (ctype) = 1; + if (CP_TYPE_CONST_P (TREE_TYPE (parmtype))) + TYPE_HAS_CONST_INIT_REF (ctype) = 1; + } + /* [class.copy] + + A declaration of a constructor for a class X is ill-formed if its + first parameter is of type (optionally cv-qualified) X and either + there are no other parameters or else all other parameters have + default arguments. + + We *don't* complain about member template instantiations that + have this form, though; they can occur as we try to decide what + constructor to use during overload resolution. Since overload + resolution will never prefer such a constructor to the + non-template copy constructor (which is either explicitly or + implicitly defined), there's no need to worry about their + existence. Theoretically, they should never even be + instantiated, but that's hard to forestall. */ + else if (TYPE_MAIN_VARIANT (parmtype) == ctype + && (TREE_CHAIN (parmtypes) == NULL_TREE + || TREE_CHAIN (parmtypes) == void_list_node + || TREE_PURPOSE (TREE_CHAIN (parmtypes))) + && !(DECL_TEMPLATE_INSTANTIATION (decl) + && is_member_template (DECL_TI_TEMPLATE (decl)))) + { + cp_error ("invalid constructor; you probably meant `%T (const %T&)'", + ctype, ctype); + SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype); + return 0; + } + else if (TREE_CODE (parmtype) == VOID_TYPE + || TREE_PURPOSE (parmtypes) != NULL_TREE) + TYPE_HAS_DEFAULT_CONSTRUCTOR (ctype) = 1; + + return 1; +} + +/* An operator with this name can be either unary or binary. */ + +static int +ambi_op_p (name) + tree name; +{ + return (name == ansi_opname [(int) INDIRECT_REF] + || name == ansi_opname [(int) ADDR_EXPR] + || name == ansi_opname [(int) NEGATE_EXPR] + || name == ansi_opname[(int) POSTINCREMENT_EXPR] + || name == ansi_opname[(int) POSTDECREMENT_EXPR] + || name == ansi_opname [(int) CONVERT_EXPR]); +} + +/* An operator with this name can only be unary. */ + +static int +unary_op_p (name) + tree name; +{ + return (name == ansi_opname [(int) TRUTH_NOT_EXPR] + || name == ansi_opname [(int) BIT_NOT_EXPR] + || name == ansi_opname [(int) COMPONENT_REF] + || IDENTIFIER_TYPENAME_P (name)); +} + +/* Do a little sanity-checking on how they declared their operator. */ + +void +grok_op_properties (decl, virtualp, friendp) + tree decl; + int virtualp, friendp; +{ + tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); + int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE); + tree name = DECL_NAME (decl); + + if (current_class_type == NULL_TREE) + friendp = 1; + + if (! friendp) + { + /* [class.copy] + + A user-declared copy assignment operator X::operator= is a + non-static non-template member function of class X with + exactly one parameter of type X, X&, const X&, volatile X& or + const volatile X&. */ + if (name == ansi_opname[(int) MODIFY_EXPR] + && !(DECL_TEMPLATE_INSTANTIATION (decl) + && is_member_template (DECL_TI_TEMPLATE (decl)))) + ; + else if (name == ansi_opname[(int) CALL_EXPR]) + TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1; + else if (name == ansi_opname[(int) ARRAY_REF]) + TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1; + else if (name == ansi_opname[(int) COMPONENT_REF] + || name == ansi_opname[(int) MEMBER_REF]) + TYPE_OVERLOADS_ARROW (current_class_type) = 1; + else if (name == ansi_opname[(int) NEW_EXPR]) + TYPE_GETS_NEW (current_class_type) |= 1; + else if (name == ansi_opname[(int) DELETE_EXPR]) + TYPE_GETS_DELETE (current_class_type) |= 1; + else if (name == ansi_opname[(int) VEC_NEW_EXPR]) + TYPE_GETS_NEW (current_class_type) |= 2; + else if (name == ansi_opname[(int) VEC_DELETE_EXPR]) + TYPE_GETS_DELETE (current_class_type) |= 2; + } + + if (name == ansi_opname[(int) NEW_EXPR] + || name == ansi_opname[(int) VEC_NEW_EXPR]) + { + /* When the compiler encounters the definition of A::operator new, it + doesn't look at the class declaration to find out if it's static. */ + if (methodp) + revert_static_member_fn (&decl, NULL, NULL); + + /* Take care of function decl if we had syntax errors. */ + if (argtypes == NULL_TREE) + TREE_TYPE (decl) + = build_function_type (ptr_type_node, + hash_tree_chain (integer_type_node, + void_list_node)); + else + TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl)); + } + else if (name == ansi_opname[(int) DELETE_EXPR] + || name == ansi_opname[(int) VEC_DELETE_EXPR]) + { + if (methodp) + revert_static_member_fn (&decl, NULL, NULL); + + if (argtypes == NULL_TREE) + TREE_TYPE (decl) + = build_function_type (void_type_node, + hash_tree_chain (ptr_type_node, + void_list_node)); + else + { + TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl)); + + if (! friendp && name == ansi_opname[(int) VEC_DELETE_EXPR] + && (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))) + != void_list_node)) + TYPE_VEC_DELETE_TAKES_SIZE (current_class_type) = 1; + } + } + else + { + /* An operator function must either be a non-static member function + or have at least one parameter of a class, a reference to a class, + an enumeration, or a reference to an enumeration. 13.4.0.6 */ + if (! methodp || DECL_STATIC_FUNCTION_P (decl)) + { + if (IDENTIFIER_TYPENAME_P (name) + || name == ansi_opname[(int) CALL_EXPR] + || name == ansi_opname[(int) MODIFY_EXPR] + || name == ansi_opname[(int) COMPONENT_REF] + || name == ansi_opname[(int) ARRAY_REF]) + cp_error ("`%D' must be a nonstatic member function", decl); + else + { + tree p = argtypes; + + if (DECL_STATIC_FUNCTION_P (decl)) + cp_error ("`%D' must be either a non-static member function or a non-member function", decl); + + if (p) + for (; TREE_CODE (TREE_VALUE (p)) != VOID_TYPE ; p = TREE_CHAIN (p)) + { + tree arg = TREE_VALUE (p); + if (TREE_CODE (arg) == REFERENCE_TYPE) + arg = TREE_TYPE (arg); + + /* This lets bad template code slip through. */ + if (IS_AGGR_TYPE (arg) + || TREE_CODE (arg) == ENUMERAL_TYPE + || TREE_CODE (arg) == TEMPLATE_TYPE_PARM + || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) + goto foundaggr; + } + cp_error + ("`%D' must have an argument of class or enumerated type", + decl); + foundaggr: + ; + } + } + + if (name == ansi_opname[(int) CALL_EXPR]) + return; /* No restrictions on args. */ + + if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl)) + { + tree t = TREE_TYPE (name); + if (TREE_CODE (t) == VOID_TYPE) + pedwarn ("void is not a valid type conversion operator"); + else if (! friendp) + { + int ref = (TREE_CODE (t) == REFERENCE_TYPE); + const char *what = 0; + if (ref) + t = TYPE_MAIN_VARIANT (TREE_TYPE (t)); + + if (t == current_class_type) + what = "the same type"; + /* Don't force t to be complete here. */ + else if (IS_AGGR_TYPE (t) + && TYPE_SIZE (t) + && DERIVED_FROM_P (t, current_class_type)) + what = "a base class"; + + if (what) + warning ("conversion to %s%s will never use a type conversion operator", + ref ? "a reference to " : "", what); + } + } + + if (name == ansi_opname[(int) MODIFY_EXPR]) + { + tree parmtype; + + if (list_length (argtypes) != 3 && methodp) + { + cp_error ("`%D' must take exactly one argument", decl); + return; + } + parmtype = TREE_VALUE (TREE_CHAIN (argtypes)); + + if (copy_assignment_arg_p (parmtype, virtualp) + && ! friendp) + { + TYPE_HAS_ASSIGN_REF (current_class_type) = 1; + if (TREE_CODE (parmtype) != REFERENCE_TYPE + || CP_TYPE_CONST_P (TREE_TYPE (parmtype))) + TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1; + } + } + else if (name == ansi_opname[(int) COND_EXPR]) + { + /* 13.4.0.3 */ + pedwarn ("ANSI C++ prohibits overloading operator ?:"); + if (list_length (argtypes) != 4) + cp_error ("`%D' must take exactly three arguments", decl); + } + else if (ambi_op_p (name)) + { + if (list_length (argtypes) == 2) + /* prefix */; + else if (list_length (argtypes) == 3) + { + if ((name == ansi_opname[(int) POSTINCREMENT_EXPR] + || name == ansi_opname[(int) POSTDECREMENT_EXPR]) + && ! processing_template_decl + && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node)) + { + if (methodp) + cp_error ("postfix `%D' must take `int' as its argument", + decl); + else + cp_error + ("postfix `%D' must take `int' as its second argument", + decl); + } + } + else + { + if (methodp) + cp_error ("`%D' must take either zero or one argument", decl); + else + cp_error ("`%D' must take either one or two arguments", decl); + } + + /* More Effective C++ rule 6. */ + if (warn_ecpp + && (name == ansi_opname[(int) POSTINCREMENT_EXPR] + || name == ansi_opname[(int) POSTDECREMENT_EXPR])) + { + tree arg = TREE_VALUE (argtypes); + tree ret = TREE_TYPE (TREE_TYPE (decl)); + if (methodp || TREE_CODE (arg) == REFERENCE_TYPE) + arg = TREE_TYPE (arg); + arg = TYPE_MAIN_VARIANT (arg); + if (list_length (argtypes) == 2) + { + if (TREE_CODE (ret) != REFERENCE_TYPE + || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)), + arg)) + cp_warning ("prefix `%D' should return `%T'", decl, + build_reference_type (arg)); + } + else + { + if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg)) + cp_warning ("postfix `%D' should return `%T'", decl, arg); + } + } + } + else if (unary_op_p (name)) + { + if (list_length (argtypes) != 2) + { + if (methodp) + cp_error ("`%D' must take `void'", decl); + else + cp_error ("`%D' must take exactly one argument", decl); + } + } + else /* if (binary_op_p (name)) */ + { + if (list_length (argtypes) != 3) + { + if (methodp) + cp_error ("`%D' must take exactly one argument", decl); + else + cp_error ("`%D' must take exactly two arguments", decl); + } + + /* More Effective C++ rule 7. */ + if (warn_ecpp + && (name == ansi_opname [TRUTH_ANDIF_EXPR] + || name == ansi_opname [TRUTH_ORIF_EXPR] + || name == ansi_opname [COMPOUND_EXPR])) + cp_warning ("user-defined `%D' always evaluates both arguments", + decl); + } + + /* Effective C++ rule 23. */ + if (warn_ecpp + && list_length (argtypes) == 3 + && (name == ansi_opname [PLUS_EXPR] + || name == ansi_opname [MINUS_EXPR] + || name == ansi_opname [TRUNC_DIV_EXPR] + || name == ansi_opname [MULT_EXPR]) + && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE) + cp_warning ("`%D' should return by value", decl); + + /* 13.4.0.8 */ + if (argtypes) + for (; argtypes != void_list_node ; argtypes = TREE_CHAIN (argtypes)) + if (TREE_PURPOSE (argtypes)) + { + TREE_PURPOSE (argtypes) = NULL_TREE; + if (name == ansi_opname[(int) POSTINCREMENT_EXPR] + || name == ansi_opname[(int) POSTDECREMENT_EXPR]) + { + if (pedantic) + cp_pedwarn ("`%D' cannot have default arguments", decl); + } + else + cp_error ("`%D' cannot have default arguments", decl); + } + } +} + +static const char * +tag_name (code) + enum tag_types code; +{ + switch (code) + { + case record_type: + return "struct"; + case class_type: + return "class"; + case union_type: + return "union "; + case enum_type: + return "enum"; + case signature_type: + return "signature"; + default: + my_friendly_abort (981122); + } +} + +/* Get the struct, enum or union (CODE says which) with tag NAME. + Define the tag as a forward-reference if it is not defined. + + C++: If a class derivation is given, process it here, and report + an error if multiple derivation declarations are not identical. + + If this is a definition, come in through xref_tag and only look in + the current frame for the name (since C++ allows new names in any + scope.) */ + +tree +xref_tag (code_type_node, name, globalize) + tree code_type_node; + tree name; + int globalize; +{ + enum tag_types tag_code; + enum tree_code code; + int temp = 0; + register tree ref, t; + struct binding_level *b = current_binding_level; + int got_type = 0; + tree attributes = NULL_TREE; + tree context = NULL_TREE; + + /* If we are called from the parser, code_type_node will sometimes be a + TREE_LIST. This indicates that the user wrote + "class __attribute__ ((foo)) bar". Extract the attributes so we can + use them later. */ + if (TREE_CODE (code_type_node) == TREE_LIST) + { + attributes = TREE_PURPOSE (code_type_node); + code_type_node = TREE_VALUE (code_type_node); + } + + tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node); + switch (tag_code) + { + case record_type: + case class_type: + case signature_type: + code = RECORD_TYPE; + break; + case union_type: + code = UNION_TYPE; + break; + case enum_type: + code = ENUMERAL_TYPE; + break; + default: + my_friendly_abort (18); + } + + /* If a cross reference is requested, look up the type + already defined for this tag and return it. */ + if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') + { + t = name; + name = TYPE_IDENTIFIER (t); + got_type = 1; + } + else + t = IDENTIFIER_TYPE_VALUE (name); + + if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM + && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM) + t = NULL_TREE; + + if (! globalize) + { + /* If we know we are defining this tag, only look it up in + this scope and don't try to find it as a type. */ + ref = lookup_tag (code, name, b, 1); + } + else + { + if (t) + { + /* [dcl.type.elab] If the identifier resolves to a + typedef-name or a template type-parameter, the + elaborated-type-specifier is ill-formed. */ + if (t != TYPE_MAIN_VARIANT (t) + || (CLASS_TYPE_P (t) && TYPE_WAS_ANONYMOUS (t))) + cp_pedwarn ("using typedef-name `%D' after `%s'", + TYPE_NAME (t), tag_name (tag_code)); + else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) + cp_error ("using template type parameter `%T' after `%s'", + t, tag_name (tag_code)); + + ref = t; + } + else + ref = lookup_tag (code, name, b, 0); + + if (! ref) + { + /* Try finding it as a type declaration. If that wins, + use it. */ + ref = lookup_name (name, 1); + + if (ref != NULL_TREE + && processing_template_decl + && DECL_CLASS_TEMPLATE_P (ref) + && template_class_depth (current_class_type) == 0) + /* Since GLOBALIZE is true, we're declaring a global + template, so we want this type. */ + ref = DECL_RESULT (ref); + + if (ref && TREE_CODE (ref) == TYPE_DECL + && TREE_CODE (TREE_TYPE (ref)) == code) + ref = TREE_TYPE (ref); + else + ref = NULL_TREE; + } + + if (ref && current_class_type + && template_class_depth (current_class_type) + && PROCESSING_REAL_TEMPLATE_DECL_P ()) + { + /* Since GLOBALIZE is non-zero, we are not looking at a + definition of this tag. Since, in addition, we are currently + processing a (member) template declaration of a template + class, we must be very careful; consider: + + template + struct S1 + + template + struct S2 + { template + friend struct S1; }; + + Here, the S2::S1 declaration should not be confused with the + outer declaration. In particular, the inner version should + have a template parameter of level 2, not level 1. This + would be particularly important if the member declaration + were instead: + + template friend struct S1; + + say, when we should tsubst into `U' when instantiating + S2. On the other hand, when presented with: + + template + struct S1 { + template + struct S2 {}; + template + friend struct S2; + }; + + we must find the inner binding eventually. We + accomplish this by making sure that the new type we + create to represent this declaration has the right + TYPE_CONTEXT. */ + context = TYPE_CONTEXT (ref); + ref = NULL_TREE; + } + } + + push_obstacks_nochange (); + + if (! ref) + { + /* If no such tag is yet defined, create a forward-reference node + and record it as the "definition". + When a real declaration of this type is found, + the forward-reference will be altered into a real type. */ + + /* In C++, since these migrate into the global scope, we must + build them on the permanent obstack. */ + + temp = allocation_temporary_p (); + if (temp) + end_temporary_allocation (); + + if (code == ENUMERAL_TYPE) + { + cp_error ("use of enum `%#D' without previous declaration", name); + + ref = make_node (ENUMERAL_TYPE); + + /* Give the type a default layout like unsigned int + to avoid crashing if it does not get defined. */ + TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node); + TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node); + TREE_UNSIGNED (ref) = 1; + TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node); + TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node); + TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node); + + /* Enable us to recognize when a type is created in class context. + To do nested classes correctly, this should probably be cleared + out when we leave this classes scope. Currently this in only + done in `start_enum'. */ + + pushtag (name, ref, globalize); + } + else + { + struct binding_level *old_b = class_binding_level; + + ref = make_lang_type (code); + TYPE_CONTEXT (ref) = context; + + if (tag_code == signature_type) + { + SET_SIGNATURE (ref); + /* Since a signature type will be turned into the type + of signature tables, it's not only an interface. */ + CLASSTYPE_INTERFACE_ONLY (ref) = 0; + SET_CLASSTYPE_INTERFACE_KNOWN (ref); + /* A signature doesn't have a vtable. */ + CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = 0; + } + +#ifdef NONNESTED_CLASSES + /* Class types don't nest the way enums do. */ + class_binding_level = (struct binding_level *)0; +#endif + pushtag (name, ref, globalize); + class_binding_level = old_b; + } + } + else + { + /* If it no longer looks like a nested type, make sure it's + in global scope. + If it is not an IDENTIFIER, this is not a declaration */ + if (b->namespace_p && !class_binding_level + && TREE_CODE (name) == IDENTIFIER_NODE) + { + if (IDENTIFIER_NAMESPACE_VALUE (name) == NULL_TREE) + SET_IDENTIFIER_NAMESPACE_VALUE (name, TYPE_NAME (ref)); + } + + if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref)) + redeclare_class_template (ref, current_template_parms); + } + + /* Until the type is defined, tentatively accept whatever + structure tag the user hands us. */ + if (TYPE_SIZE (ref) == NULL_TREE + && ref != current_class_type + /* Have to check this, in case we have contradictory tag info. */ + && IS_AGGR_TYPE_CODE (TREE_CODE (ref))) + { + if (tag_code == class_type) + CLASSTYPE_DECLARED_CLASS (ref) = 1; + else if (tag_code == record_type || tag_code == signature_type) + CLASSTYPE_DECLARED_CLASS (ref) = 0; + } + + pop_obstacks (); + + TREE_TYPE (ref) = attributes; + + return ref; +} + +tree +xref_tag_from_type (old, id, globalize) + tree old, id; + int globalize; +{ + tree code_type_node; + + if (TREE_CODE (old) == RECORD_TYPE) + code_type_node = (CLASSTYPE_DECLARED_CLASS (old) + ? class_type_node : record_type_node); + else + code_type_node = union_type_node; + + if (id == NULL_TREE) + id = TYPE_IDENTIFIER (old); + + return xref_tag (code_type_node, id, globalize); +} + +/* REF is a type (named NAME), for which we have just seen some + baseclasses. BINFO is a list of those baseclasses; the + TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of + the base-class. CODE_TYPE_NODE indicates whether REF is a class, + struct, or union. */ + +void +xref_basetypes (code_type_node, name, ref, binfo) + tree code_type_node; + tree name, ref; + tree binfo; +{ + /* In the declaration `A : X, Y, ... Z' we mark all the types + (A, X, Y, ..., Z) so we can check for duplicates. */ + tree binfos; + tree base; + + int i, len; + enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node); + + if (tag_code == union_type) + { + cp_error ("derived union `%T' invalid", ref); + return; + } + + len = list_length (binfo); + push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref)); + + /* First, make sure that any templates in base-classes are + instantiated. This ensures that if we call ourselves recursively + we do not get confused about which classes are marked and which + are not. */ + for (base = binfo; base; base = TREE_CHAIN (base)) + complete_type (TREE_VALUE (base)); + + SET_CLASSTYPE_MARKED (ref); + BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len); + + for (i = 0; binfo; binfo = TREE_CHAIN (binfo)) + { + /* The base of a derived struct is public by default. */ + int via_public + = (TREE_PURPOSE (binfo) == access_public_node + || TREE_PURPOSE (binfo) == access_public_virtual_node + || (tag_code != class_type + && (TREE_PURPOSE (binfo) == access_default_node + || TREE_PURPOSE (binfo) == access_default_virtual_node))); + int via_protected + = (TREE_PURPOSE (binfo) == access_protected_node + || TREE_PURPOSE (binfo) == access_protected_virtual_node); + int via_virtual + = (TREE_PURPOSE (binfo) == access_private_virtual_node + || TREE_PURPOSE (binfo) == access_protected_virtual_node + || TREE_PURPOSE (binfo) == access_public_virtual_node + || TREE_PURPOSE (binfo) == access_default_virtual_node); + tree basetype = TREE_VALUE (binfo); + tree base_binfo; + + if (basetype && TREE_CODE (basetype) == TYPE_DECL) + basetype = TREE_TYPE (basetype); + if (!basetype + || (TREE_CODE (basetype) != RECORD_TYPE + && TREE_CODE (basetype) != TYPENAME_TYPE + && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM + && TREE_CODE (basetype) != TEMPLATE_TEMPLATE_PARM)) + { + cp_error ("base type `%T' fails to be a struct or class type", + TREE_VALUE (binfo)); + continue; + } + + GNU_xref_hier (name, basetype, via_public, via_virtual, 0); + + /* This code replaces similar code in layout_basetypes. + We put the complete_type first for implicit `typename'. */ + if (TYPE_SIZE (basetype) == NULL_TREE + && ! (current_template_parms && uses_template_parms (basetype))) + { + cp_error ("base class `%T' has incomplete type", basetype); + continue; + } + else + { + if (CLASSTYPE_MARKED (basetype)) + { + if (basetype == ref) + cp_error ("recursive type `%T' undefined", basetype); + else + cp_error ("duplicate base type `%T' invalid", basetype); + continue; + } + + if (TYPE_FOR_JAVA (basetype) + && current_lang_stack == current_lang_base) + TYPE_FOR_JAVA (ref) = 1; + + /* Note that the BINFO records which describe individual + inheritances are *not* shared in the lattice! They + cannot be shared because a given baseclass may be + inherited with different `accessibility' by different + derived classes. (Each BINFO record describing an + individual inheritance contains flags which say what + the `accessibility' of that particular inheritance is.) */ + + base_binfo + = make_binfo (integer_zero_node, basetype, + CLASS_TYPE_P (basetype) + ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE, + CLASS_TYPE_P (basetype) + ? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE); + + TREE_VEC_ELT (binfos, i) = base_binfo; + TREE_VIA_PUBLIC (base_binfo) = via_public; + TREE_VIA_PROTECTED (base_binfo) = via_protected; + TREE_VIA_VIRTUAL (base_binfo) = via_virtual; + BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref); + + /* We need to unshare the binfos now so that lookups during class + definition work. */ + unshare_base_binfos (base_binfo); + + SET_CLASSTYPE_MARKED (basetype); + + /* We are free to modify these bits because they are meaningless + at top level, and BASETYPE is a top-level type. */ + if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype)) + { + TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1; + TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; + /* The PVBASES flag is never set for templates; we know + only for instantiations whether the virtual bases are + polymorphic. */ + if (flag_vtable_thunks >= 2 && !CLASSTYPE_IS_TEMPLATE (ref)) + { + if (via_virtual && TYPE_VIRTUAL_P (basetype)) + TYPE_USES_PVBASES (ref) = 1; + else if (TYPE_USES_PVBASES (basetype)) + TYPE_USES_PVBASES (ref) = 1; + } + } + + if (CLASS_TYPE_P (basetype)) + { + TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype); + TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); + } + + i += 1; + } + } + if (i) + TREE_VEC_LENGTH (binfos) = i; + else + BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE; + + if (i > 1) + TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1; + else if (i == 1) + { + tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, 0)); + + if (CLASS_TYPE_P (basetype)) + TYPE_USES_MULTIPLE_INHERITANCE (ref) + = TYPE_USES_MULTIPLE_INHERITANCE (basetype); + } + + if (TYPE_USES_MULTIPLE_INHERITANCE (ref)) + TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; + + /* Unmark all the types. */ + while (--i >= 0) + CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i))); + CLEAR_CLASSTYPE_MARKED (ref); + + /* Now that we know all the base-classes, set up the list of virtual + bases. */ + CLASSTYPE_VBASECLASSES (ref) = get_vbase_types (ref); + + pop_obstacks (); +} + + +/* Begin compiling the definition of an enumeration type. + NAME is its name (or null if anonymous). + Returns the type object, as yet incomplete. + Also records info about it so that build_enumerator + may be used to declare the individual values as they are read. */ + +tree +start_enum (name) + tree name; +{ + register tree enumtype = NULL_TREE; + struct binding_level *b = current_binding_level; + + /* We are wasting space here and putting these on the permanent_obstack so + that typeid(local enum) will work correctly. */ + push_obstacks (&permanent_obstack, &permanent_obstack); + + /* If this is the real definition for a previous forward reference, + fill in the contents in the same object that used to be the + forward reference. */ + + if (name != NULL_TREE) + enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1); + + if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE) + cp_error ("multiple definition of `%#T'", enumtype); + else + { + enumtype = make_node (ENUMERAL_TYPE); + pushtag (name, enumtype, 0); + } + + if (current_class_type) + TREE_ADDRESSABLE (b->tags) = 1; + + /* We don't copy this value because build_enumerator needs to do it. */ + enum_next_value = integer_zero_node; + enum_overflow = 0; + + GNU_xref_decl (current_function_decl, enumtype); + return enumtype; +} + +/* After processing and defining all the values of an enumeration type, + install their decls in the enumeration type and finish it off. + ENUMTYPE is the type object and VALUES a list of name-value pairs. + Returns ENUMTYPE. */ + +tree +finish_enum (enumtype) + tree enumtype; +{ + register tree minnode = NULL_TREE, maxnode = NULL_TREE; + /* Calculate the maximum value of any enumerator in this type. */ + + tree values = TYPE_VALUES (enumtype); + if (values) + { + tree pair; + + for (pair = values; pair; pair = TREE_CHAIN (pair)) + { + tree decl; + tree value; + + /* The TREE_VALUE is a CONST_DECL for this enumeration + constant. */ + decl = TREE_VALUE (pair); + + /* The DECL_INITIAL will be NULL if we are processing a + template declaration and this enumeration constant had no + explicit initializer. */ + value = DECL_INITIAL (decl); + if (value && !processing_template_decl) + { + /* Set the TREE_TYPE for the VALUE as well. That's so + that when we call decl_constant_value we get an + entity of the right type (but with the constant + value). Since we shouldn't ever call + decl_constant_value on a template type, there's no + reason to do that when processing_template_decl. + And, if the expression is something like a + TEMPLATE_PARM_INDEX or a CAST_EXPR doing so will + wreak havoc on the intended type of the expression. + + Of course, there's also no point in trying to compute + minimum or maximum values if we're in a template. */ + TREE_TYPE (value) = enumtype; + + if (!minnode) + minnode = maxnode = value; + else if (tree_int_cst_lt (maxnode, value)) + maxnode = value; + else if (tree_int_cst_lt (value, minnode)) + minnode = value; + } + + if (processing_template_decl) + /* If this is just a template, leave the CONST_DECL + alone. That way tsubst_copy will find CONST_DECLs for + CONST_DECLs, and not INTEGER_CSTs. */ + ; + else + /* In the list we're building up, we want the enumeration + values, not the CONST_DECLs. */ + TREE_VALUE (pair) = value; + } + } + else + maxnode = minnode = integer_zero_node; + + TYPE_VALUES (enumtype) = nreverse (values); + + if (processing_template_decl) + { + tree scope = current_scope (); + if (scope && TREE_CODE (scope) == FUNCTION_DECL) + add_tree (build_min (TAG_DEFN, enumtype)); + } + else + { + int unsignedp = tree_int_cst_sgn (minnode) >= 0; + int lowprec = min_precision (minnode, unsignedp); + int highprec = min_precision (maxnode, unsignedp); + int precision = MAX (lowprec, highprec); + tree tem; + + TYPE_SIZE (enumtype) = NULL_TREE; + + /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */ + + TYPE_PRECISION (enumtype) = precision; + if (unsignedp) + fixup_unsigned_type (enumtype); + else + fixup_signed_type (enumtype); + + if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node))) + /* Use the width of the narrowest normal C type which is wide + enough. */ + TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size + (precision, 1)); + else + TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); + + TYPE_SIZE (enumtype) = 0; + layout_type (enumtype); + + /* Fix up all variant types of this enum type. */ + for (tem = TYPE_MAIN_VARIANT (enumtype); tem; + tem = TYPE_NEXT_VARIANT (tem)) + { + TYPE_VALUES (tem) = TYPE_VALUES (enumtype); + TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype); + TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype); + TYPE_SIZE (tem) = TYPE_SIZE (enumtype); + TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype); + TYPE_MODE (tem) = TYPE_MODE (enumtype); + TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype); + TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype); + TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype); + } + + /* Finish debugging output for this type. */ + rest_of_type_compilation (enumtype, namespace_bindings_p ()); + } + + /* In start_enum we pushed obstacks. Here, we must pop them. */ + pop_obstacks (); + + return enumtype; +} + +/* Build and install a CONST_DECL for an enumeration constant of the + enumeration type TYPE whose NAME and VALUE (if any) are provided. + Assignment of sequential values by default is handled here. */ + +tree +build_enumerator (name, value, type) + tree name; + tree value; + tree type; +{ + tree decl, result; + tree context; + + /* Remove no-op casts from the value. */ + if (value) + STRIP_TYPE_NOPS (value); + + if (! processing_template_decl) + { + /* Validate and default VALUE. */ + if (value != NULL_TREE) + { + if (TREE_READONLY_DECL_P (value)) + value = decl_constant_value (value); + + if (TREE_CODE (value) == INTEGER_CST) + { + value = default_conversion (value); + constant_expression_warning (value); + } + else + { + cp_error ("enumerator value for `%D' not integer constant", name); + value = NULL_TREE; + } + } + + /* Default based on previous value. */ + if (value == NULL_TREE && ! processing_template_decl) + { + value = enum_next_value; + if (enum_overflow) + cp_error ("overflow in enumeration values at `%D'", name); + } + + /* Remove no-op casts from the value. */ + if (value) + STRIP_TYPE_NOPS (value); +#if 0 + /* To fix MAX_VAL enum consts. (bkoz) */ + TREE_TYPE (value) = integer_type_node; +#endif + } + + /* We always have to copy here; not all INTEGER_CSTs are unshared. + Even in other cases, we will later (in finish_enum) be setting the + type of VALUE. */ + if (value != NULL_TREE) + value = copy_node (value); + + /* C++ associates enums with global, function, or class declarations. */ + + context = current_scope (); + if (context && context == current_class_type) + /* This enum declaration is local to the class. */ + decl = build_lang_field_decl (CONST_DECL, name, type); + else + /* It's a global enum, or it's local to a function. (Note local to + a function could mean local to a class method. */ + decl = build_decl (CONST_DECL, name, type); + + DECL_CONTEXT (decl) = FROB_CONTEXT (context); + DECL_INITIAL (decl) = value; + TREE_READONLY (decl) = 1; + + if (context && context == current_class_type) + /* In something like `struct S { enum E { i = 7 }; };' we put `i' + on the TYPE_FIELDS list for `S'. (That's so that you can say + things like `S::i' later.) */ + finish_member_declaration (decl); + else + { + pushdecl (decl); + GNU_xref_decl (current_function_decl, decl); + } + + if (! processing_template_decl) + { + /* Set basis for default for next value. */ + enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value, + integer_one_node, PLUS_EXPR); + enum_overflow = tree_int_cst_lt (enum_next_value, value); + } + + result = saveable_tree_cons (name, decl, NULL_TREE); + return result; +} + + +static int function_depth; + +/* Create the FUNCTION_DECL for a function definition. + DECLSPECS and DECLARATOR are the parts of the declaration; + they describe the function's name and the type it returns, + but twisted together in a fashion that parallels the syntax of C. + + If PRE_PARSED_P is non-zero then DECLARATOR is really the DECL for + the function we are about to process; DECLSPECS are ignored. For + example, we set PRE_PARSED_P when processing the definition of + inline function that was defined in-class; the definition is + actually processed when the class is complete. In this case, + PRE_PARSED_P is 2. We also set PRE_PARSED_P when instanting the + body of a template function, and when constructing thunk functions + and such; in these cases PRE_PARSED_P is 1. + + This function creates a binding context for the function body + as well as setting up the FUNCTION_DECL in current_function_decl. + + Returns 1 on success. If the DECLARATOR is not suitable for a function + (it defines a datum instead), we return 0, which tells + yyparse to report a parse error. + + For C++, we must first check whether that datum makes any sense. + For example, "class A local_a(1,2);" means that variable local_a + is an aggregate of type A, which should have a constructor + applied to it with the argument list [1, 2]. + + @@ There is currently no way to retrieve the storage + @@ allocated to FUNCTION (or all of its parms) if we return + @@ something we had previously. */ + +int +start_function (declspecs, declarator, attrs, pre_parsed_p) + tree declspecs, declarator, attrs; + int pre_parsed_p; +{ + tree decl1; + tree ctype = NULL_TREE; + tree fntype; + tree restype; + extern int have_extern_spec; + extern int used_extern_spec; + int doing_friend = 0; + + /* Sanity check. */ + my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160); + my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161); + + /* Assume, until we see it does. */ + current_function_returns_value = 0; + current_function_returns_null = 0; + named_labels = 0; + shadowed_labels = 0; + current_function_assigns_this = 0; + current_function_just_assigned_this = 0; + current_function_parms_stored = 0; + original_result_rtx = NULL_RTX; + base_init_expr = NULL_TREE; + current_base_init_list = NULL_TREE; + current_member_init_list = NULL_TREE; + ctor_label = dtor_label = NULL_TREE; + static_labelno = 0; + + clear_temp_name (); + + /* This should only be done once on the top most decl. */ + if (have_extern_spec && !used_extern_spec) + { + declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs); + used_extern_spec = 1; + } + + if (pre_parsed_p) + { + decl1 = declarator; + +#if 0 + /* What was this testing for, exactly? */ + if (! DECL_ARGUMENTS (decl1) + && !DECL_STATIC_FUNCTION_P (decl1) + && !DECL_ARTIFICIAL (decl1) + && DECL_CLASS_SCOPE_P (decl1) + && TYPE_IDENTIFIER (DECL_CONTEXT (decl1)) + && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (DECL_CONTEXT (decl1)))) + { + tree binding = binding_for_name (DECL_NAME (decl1), + current_namespace); + cp_error ("redeclaration of `%#D'", decl1); + if (IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1))) + cp_error_at ("previous declaration here", IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1))); + else if (BINDING_VALUE (binding)) + cp_error_at ("previous declaration here", BINDING_VALUE (binding)); + } +#endif + + fntype = TREE_TYPE (decl1); + if (TREE_CODE (fntype) == METHOD_TYPE) + ctype = TYPE_METHOD_BASETYPE (fntype); + + /* ANSI C++ June 5 1992 WP 11.4.5. A friend function defined in a + class is in the (lexical) scope of the class in which it is + defined. */ + if (!ctype && DECL_FRIEND_P (decl1)) + { + ctype = DECL_CLASS_CONTEXT (decl1); + + /* CTYPE could be null here if we're dealing with a template; + for example, `inline friend float foo()' inside a template + will have no CTYPE set. */ + if (ctype && TREE_CODE (ctype) != RECORD_TYPE) + ctype = NULL_TREE; + else + doing_friend = 1; + } + + last_function_parms = DECL_ARGUMENTS (decl1); + last_function_parm_tags = NULL_TREE; + } + else + { + decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL_TREE); + /* If the declarator is not suitable for a function definition, + cause a syntax error. */ + if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0; + + fntype = TREE_TYPE (decl1); + + restype = TREE_TYPE (fntype); + if (CLASS_TYPE_P (restype) && !CLASSTYPE_GOT_SEMICOLON (restype)) + { + cp_error ("semicolon missing after declaration of `%#T'", restype); + shadow_tag (build_expr_list (NULL_TREE, restype)); + CLASSTYPE_GOT_SEMICOLON (restype) = 1; + if (TREE_CODE (fntype) == FUNCTION_TYPE) + fntype = build_function_type (integer_type_node, + TYPE_ARG_TYPES (fntype)); + else + fntype = build_cplus_method_type (build_type_variant (TYPE_METHOD_BASETYPE (fntype), TREE_READONLY (decl1), TREE_SIDE_EFFECTS (decl1)), + integer_type_node, + TYPE_ARG_TYPES (fntype)); + TREE_TYPE (decl1) = fntype; + } + + if (TREE_CODE (fntype) == METHOD_TYPE) + ctype = TYPE_METHOD_BASETYPE (fntype); + else if (DECL_MAIN_P (decl1)) + { + /* If this doesn't return integer_type, complain. */ + if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node) + { + if (pedantic || warn_return_type) + pedwarn ("return type for `main' changed to `int'"); + TREE_TYPE (decl1) = fntype = default_function_type; + } + } + } + + /* Warn if function was previously implicitly declared + (but not if we warned then). */ + if (! warn_implicit + && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE) + cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1))); + + announce_function (decl1); + + /* Set up current_class_type, and enter the scope of the class, if + appropriate. */ + if (ctype) + push_nested_class (ctype, 1); + else if (DECL_STATIC_FUNCTION_P (decl1)) + push_nested_class (DECL_CONTEXT (decl1), 2); + + /* Now that we have entered the scope of the class, we must restore + the bindings for any template parameters surrounding DECL1, if it + is an inline member template. (Order is important; consider the + case where a template parameter has the same name as a field of + the class.) It is not until after this point that + PROCESSING_TEMPLATE_DECL is guaranteed to be set up correctly. */ + if (pre_parsed_p == 2) + maybe_begin_member_template_processing (decl1); + + /* We are now in the scope of the function being defined. */ + current_function_decl = decl1; + + /* Save the parm names or decls from this function's declarator + where store_parm_decls will find them. */ + current_function_parms = last_function_parms; + current_function_parm_tags = last_function_parm_tags; + + if (! processing_template_decl) + { + /* In a function definition, arg types must be complete. */ + require_complete_types_for_parms (current_function_parms); + + if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE) + { + cp_error ("return-type `%#T' is an incomplete type", + TREE_TYPE (fntype)); + + /* Make it return void instead, but don't change the + type of the DECL_RESULT, in case we have a named return value. */ + if (ctype) + TREE_TYPE (decl1) + = build_cplus_method_type (build_type_variant (ctype, + TREE_READONLY (decl1), + TREE_SIDE_EFFECTS (decl1)), + void_type_node, + FUNCTION_ARG_CHAIN (decl1)); + else + TREE_TYPE (decl1) + = build_function_type (void_type_node, + TYPE_ARG_TYPES (TREE_TYPE (decl1))); + DECL_RESULT (decl1) + = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype))); + TREE_READONLY (DECL_RESULT (decl1)) + = CP_TYPE_CONST_P (TREE_TYPE (fntype)); + TREE_THIS_VOLATILE (DECL_RESULT (decl1)) + = CP_TYPE_VOLATILE_P (TREE_TYPE (fntype)); + } + + if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype)) + && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype))) + abstract_virtuals_error (decl1, TREE_TYPE (fntype)); + } + + /* Effective C++ rule 15. See also c_expand_return. */ + if (warn_ecpp + && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR] + && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE) + cp_warning ("`operator=' should return a reference to `*this'"); + + /* Make the init_value nonzero so pushdecl knows this is not tentative. + error_mark_node is replaced below (in poplevel) with the BLOCK. */ + DECL_INITIAL (decl1) = error_mark_node; + +#ifdef SET_DEFAULT_DECL_ATTRIBUTES + SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs); +#endif + + /* This function exists in static storage. + (This does not mean `static' in the C sense!) */ + TREE_STATIC (decl1) = 1; + + /* We must call push_template_decl after current_class_type is set + up. (If we are processing inline definitions after exiting a + class scope, current_class_type will be NULL_TREE until set above + by push_nested_class.) */ + if (processing_template_decl) + decl1 = push_template_decl (decl1); + + /* Record the decl so that the function name is defined. + If we already have a decl for this name, and it is a FUNCTION_DECL, + use the old decl. */ + if (!processing_template_decl && pre_parsed_p == 0) + { + /* A specialization is not used to guide overload resolution. */ + if ((flag_guiding_decls + || !DECL_TEMPLATE_SPECIALIZATION (decl1)) + && ! DECL_FUNCTION_MEMBER_P (decl1)) + decl1 = pushdecl (decl1); + else + { + /* We need to set the DECL_CONTEXT. */ + if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1)) + DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1)); + /* And make sure we have enough default args. */ + check_default_args (decl1); + } + DECL_MAIN_VARIANT (decl1) = decl1; + fntype = TREE_TYPE (decl1); + } + + current_function_decl = decl1; + + if (DECL_INTERFACE_KNOWN (decl1)) + { + tree ctx = hack_decl_function_context (decl1); + + if (DECL_NOT_REALLY_EXTERN (decl1)) + DECL_EXTERNAL (decl1) = 0; + + if (ctx != NULL_TREE && DECL_THIS_INLINE (ctx) + && TREE_PUBLIC (ctx)) + /* This is a function in a local class in an extern inline + function. */ + comdat_linkage (decl1); + } + /* If this function belongs to an interface, it is public. + If it belongs to someone else's interface, it is also external. + This only affects inlines and template instantiations. */ + else if (interface_unknown == 0 + && (! DECL_TEMPLATE_INSTANTIATION (decl1) + || flag_alt_external_templates)) + { + if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1) + || processing_template_decl) + { + DECL_EXTERNAL (decl1) + = (interface_only + || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines + && !DECL_VINDEX (decl1))); + + /* For WIN32 we also want to put these in linkonce sections. */ + maybe_make_one_only (decl1); + } + else + DECL_EXTERNAL (decl1) = 0; + DECL_NOT_REALLY_EXTERN (decl1) = 0; + DECL_INTERFACE_KNOWN (decl1) = 1; + } + else if (interface_unknown && interface_only + && (! DECL_TEMPLATE_INSTANTIATION (decl1) + || flag_alt_external_templates)) + { + /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma + interface, we will have interface_only set but not + interface_known. In that case, we don't want to use the normal + heuristics because someone will supply a #pragma implementation + elsewhere, and deducing it here would produce a conflict. */ + comdat_linkage (decl1); + DECL_EXTERNAL (decl1) = 0; + DECL_INTERFACE_KNOWN (decl1) = 1; + DECL_DEFER_OUTPUT (decl1) = 1; + } + else + { + /* This is a definition, not a reference. + So clear DECL_EXTERNAL. */ + DECL_EXTERNAL (decl1) = 0; + + if ((DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)) + && ! DECL_INTERFACE_KNOWN (decl1) + /* Don't try to defer nested functions for now. */ + && ! hack_decl_function_context (decl1)) + DECL_DEFER_OUTPUT (decl1) = 1; + else + DECL_INTERFACE_KNOWN (decl1) = 1; + } + + if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)) + { + if (TREE_CODE (fntype) == METHOD_TYPE) + TREE_TYPE (decl1) = fntype + = build_function_type (TREE_TYPE (fntype), + TREE_CHAIN (TYPE_ARG_TYPES (fntype))); + current_function_parms = TREE_CHAIN (current_function_parms); + DECL_ARGUMENTS (decl1) = current_function_parms; + ctype = NULL_TREE; + } + restype = TREE_TYPE (fntype); + + if (ctype) + { + /* If we're compiling a friend function, neither of the variables + current_class_ptr nor current_class_type will have values. */ + if (! doing_friend) + { + /* We know that this was set up by `grokclassfn'. + We do not wait until `store_parm_decls', since evil + parse errors may never get us to that point. Here + we keep the consistency between `current_class_type' + and `current_class_ptr'. */ + tree t = current_function_parms; + + my_friendly_assert (t != NULL_TREE + && TREE_CODE (t) == PARM_DECL, 162); + + if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE) + { + int i; + + if (! hack_decl_function_context (decl1)) + temporary_allocation (); + i = suspend_momentary (); + + /* Normally, build_indirect_ref returns + current_class_ref whenever current_class_ptr is + dereferenced. This time, however, we want it to + *create* current_class_ref, so we temporarily clear + current_class_ptr to fool it. */ + current_class_ptr = NULL_TREE; + current_class_ref = build_indirect_ref (t, NULL_PTR); + current_class_ptr = t; + + resume_momentary (i); + if (! hack_decl_function_context (decl1)) + end_temporary_allocation (); + } + else + /* We're having a signature pointer here. */ + current_class_ref = current_class_ptr = t; + + } + } + else + current_class_ptr = current_class_ref = NULL_TREE; + + pushlevel (0); + current_binding_level->parm_flag = 1; + + GNU_xref_function (decl1, current_function_parms); + + if (attrs) + cplus_decl_attributes (decl1, NULL_TREE, attrs); + + make_function_rtl (decl1); + + /* Promote the value to int before returning it. */ + if (C_PROMOTING_INTEGER_TYPE_P (restype)) + restype = type_promotes_to (restype); + + /* If this fcn was already referenced via a block-scope `extern' decl + (or an implicit decl), propagate certain information about the usage. */ + if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl1))) + TREE_ADDRESSABLE (decl1) = 1; + + if (DECL_RESULT (decl1) == NULL_TREE) + { + DECL_RESULT (decl1) + = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype)); + TREE_READONLY (DECL_RESULT (decl1)) = CP_TYPE_CONST_P (restype); + TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = CP_TYPE_VOLATILE_P (restype); + } + + /* Allocate further tree nodes temporarily during compilation + of this function only. Tiemann moved up here from bottom of fn. */ + /* If this is a nested function, then we must continue to allocate RTL + on the permanent obstack in case we need to inline it later. */ + if (! hack_decl_function_context (decl1)) + temporary_allocation (); + + if (processing_template_decl) + { + ++minimal_parse_mode; + last_tree = DECL_SAVED_TREE (decl1) + = build_nt (EXPR_STMT, void_zero_node); + } + + ++function_depth; + + if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1)) + && DECL_LANGUAGE (decl1) == lang_cplusplus) + { + dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + ctor_label = NULL_TREE; + } + else + { + dtor_label = NULL_TREE; + if (DECL_CONSTRUCTOR_P (decl1)) + ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + } + + return 1; +} + +/* Called after store_parm_decls for a function-try-block. We need to update + last_parm_cleanup_insn so that the base initializers for a constructor + are run within this block, not before it. */ + +void +expand_start_early_try_stmts () +{ + expand_start_try_stmts (); + last_parm_cleanup_insn = get_last_insn (); +} + +/* Store the parameter declarations into the current function declaration. + This is called after parsing the parameter declarations, before + digesting the body of the function. + + Also install to binding contour return value identifier, if any. */ + +void +store_parm_decls () +{ + register tree fndecl = current_function_decl; + register tree parm; + int parms_have_cleanups = 0; + tree cleanups = NULL_TREE; + + /* This is either a chain of PARM_DECLs (when a prototype is used). */ + tree specparms = current_function_parms; + + /* This is a list of types declared among parms in a prototype. */ + tree parmtags = current_function_parm_tags; + + /* This is a chain of any other decls that came in among the parm + declarations. If a parm is declared with enum {foo, bar} x; + then CONST_DECLs for foo and bar are put here. */ + tree nonparms = NULL_TREE; + + if (toplevel_bindings_p ()) + fatal ("parse errors have confused me too much"); + + /* Initialize RTL machinery. */ + init_function_start (fndecl, input_filename, lineno); + + /* Create a binding level for the parms. */ + expand_start_bindings (0); + + if (specparms != NULL_TREE) + { + /* This case is when the function was defined with an ANSI prototype. + The parms already have decls, so we need not do anything here + except record them as in effect + and complain if any redundant old-style parm decls were written. */ + + register tree next; + + /* Must clear this because it might contain TYPE_DECLs declared + at class level. */ + storedecls (NULL_TREE); + + for (parm = nreverse (specparms); parm; parm = next) + { + next = TREE_CHAIN (parm); + if (TREE_CODE (parm) == PARM_DECL) + { + tree cleanup; + if (DECL_NAME (parm) == NULL_TREE) + { + pushdecl (parm); + } + else if (TREE_CODE (TREE_TYPE (parm)) == VOID_TYPE) + cp_error ("parameter `%D' declared void", parm); + else + { + /* Now fill in DECL_REFERENCE_SLOT for any of the parm decls. + A parameter is assumed not to have any side effects. + If this should change for any reason, then this + will have to wrap the bashed reference type in a save_expr. + + Also, if the parameter type is declared to be an X + and there is an X(X&) constructor, we cannot lay it + into the stack (any more), so we make this parameter + look like it is really of reference type. Functions + which pass parameters to this function will know to + create a temporary in their frame, and pass a reference + to that. */ + + if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE + && TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm)))) + SET_DECL_REFERENCE_SLOT (parm, convert_from_reference (parm)); + + pushdecl (parm); + } + if (! processing_template_decl + && (cleanup = maybe_build_cleanup (parm), cleanup)) + { + expand_decl (parm); + parms_have_cleanups = 1; + + /* Keep track of the cleanups. */ + cleanups = tree_cons (parm, cleanup, cleanups); + } + } + else + { + /* If we find an enum constant or a type tag, + put it aside for the moment. */ + TREE_CHAIN (parm) = NULL_TREE; + nonparms = chainon (nonparms, parm); + } + } + + /* Get the decls in their original chain order + and record in the function. This is all and only the + PARM_DECLs that were pushed into scope by the loop above. */ + DECL_ARGUMENTS (fndecl) = getdecls (); + + storetags (chainon (parmtags, gettags ())); + } + else + DECL_ARGUMENTS (fndecl) = NULL_TREE; + + /* Now store the final chain of decls for the arguments + as the decl-chain of the current lexical scope. + Put the enumerators in as well, at the front so that + DECL_ARGUMENTS is not modified. */ + + storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl))); + + /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */ + declare_function_name (); + + /* Initialize the RTL code for the function. */ + DECL_SAVED_INSNS (fndecl) = NULL_RTX; + if (! processing_template_decl) + expand_function_start (fndecl, parms_have_cleanups); + + current_function_parms_stored = 1; + + /* If this function is `main', emit a call to `__main' + to run global initializers, etc. */ + if (DECL_MAIN_P (fndecl)) + expand_main_function (); + + /* Now that we have initialized the parms, we can start their + cleanups. We cannot do this before, since expand_decl_cleanup + should not be called before the parm can be used. */ + if (cleanups + && ! processing_template_decl) + { + for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups)) + { + if (! expand_decl_cleanup (TREE_PURPOSE (cleanups), TREE_VALUE (cleanups))) + cp_error ("parser lost in parsing declaration of `%D'", + TREE_PURPOSE (cleanups)); + } + } + + /* Create a binding contour which can be used to catch + cleanup-generated temporaries. Also, if the return value needs or + has initialization, deal with that now. */ + if (parms_have_cleanups) + { + pushlevel (0); + expand_start_bindings (0); + } + + if (! processing_template_decl && flag_exceptions) + { + /* Do the starting of the exception specifications, if we have any. */ + if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))) + expand_start_eh_spec (); + } + + last_parm_cleanup_insn = get_last_insn (); + last_dtor_insn = get_last_insn (); +} + +/* Bind a name and initialization to the return value of + the current function. */ + +void +store_return_init (return_id, init) + tree return_id, init; +{ + tree decl = DECL_RESULT (current_function_decl); + + if (pedantic) + /* Give this error as many times as there are occurrences, + so that users can use Emacs compilation buffers to find + and fix all such places. */ + pedwarn ("ANSI C++ does not permit named return values"); + + if (return_id != NULL_TREE) + { + if (DECL_NAME (decl) == NULL_TREE) + { + DECL_NAME (decl) = return_id; + DECL_ASSEMBLER_NAME (decl) = return_id; + } + else + cp_error ("return identifier `%D' already in place", decl); + } + + /* Can't let this happen for constructors. */ + if (DECL_CONSTRUCTOR_P (current_function_decl)) + { + error ("can't redefine default return value for constructors"); + return; + } + + /* If we have a named return value, put that in our scope as well. */ + if (DECL_NAME (decl) != NULL_TREE) + { + /* If this named return value comes in a register, + put it in a pseudo-register. */ + if (DECL_REGISTER (decl)) + { + original_result_rtx = DECL_RTL (decl); + DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl)); + } + + /* Let `cp_finish_decl' know that this initializer is ok. */ + DECL_INITIAL (decl) = init; + pushdecl (decl); + + if (minimal_parse_mode) + add_tree (build_min_nt (RETURN_INIT, return_id, + copy_to_permanent (init))); + else + cp_finish_decl (decl, init, NULL_TREE, 0, 0); + } +} + + +/* Emit implicit code for a destructor. This is a subroutine of + finish_function. */ + +static void +finish_dtor () +{ + tree binfo = TYPE_BINFO (current_class_type); + tree cond = integer_one_node; + tree exprstmt; + tree in_charge_node = lookup_name (in_charge_identifier, 0); + tree virtual_size; + int ok_to_optimize_dtor = 0; + int empty_dtor = get_last_insn () == last_dtor_insn; + rtx insns, last_parm_insn; + + if (current_function_assigns_this) + cond = build (NE_EXPR, boolean_type_node, + current_class_ptr, integer_zero_node); + else + { + int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type); + + /* If this destructor is empty, then we don't need to check + whether `this' is NULL in some cases. */ + if ((flag_this_is_variable & 1) == 0) + ok_to_optimize_dtor = 1; + else if (empty_dtor) + ok_to_optimize_dtor + = (n_baseclasses == 0 + || (n_baseclasses == 1 + && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0)))); + } + + /* If this has a vlist1 parameter, allocate the corresponding vlist + parameter. */ + if (DECL_DESTRUCTOR_FOR_PVBASE_P (current_function_decl)) + { + /* _Vlist __vlist; */ + tree vlist; + + mark_all_temps_used(); + vlist = pushdecl (build_decl (VAR_DECL, vlist_identifier, + vlist_type_node)); + TREE_USED (vlist) = 1; + DECL_ARTIFICIAL (vlist) = 1; + expand_decl (vlist); + expand_decl_init (vlist); + } + + /* These initializations might go inline. Protect + the binding level of the parms. */ + pushlevel (0); + expand_start_bindings (0); + + if (current_function_assigns_this) + { + current_function_assigns_this = 0; + current_function_just_assigned_this = 0; + } + + /* Generate the code to call destructor on base class. + If this destructor belongs to a class with virtual + functions, then set the virtual function table + pointer to represent the type of our base class. */ + + /* This side-effect makes call to `build_delete' generate the + code we have to have at the end of this destructor. + `build_delete' will set the flag again. */ + TYPE_HAS_DESTRUCTOR (current_class_type) = 0; + + /* These are two cases where we cannot delegate deletion. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type) + || TYPE_GETS_REG_DELETE (current_class_type)) + exprstmt = build_delete + (current_class_type, current_class_ref, integer_zero_node, + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0); + else + exprstmt = build_delete + (current_class_type, current_class_ref, in_charge_node, + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0); + + /* If we did not assign to this, then `this' is non-zero at + the end of a destructor. As a special optimization, don't + emit test if this is an empty destructor. If it does nothing, + it does nothing. If it calls a base destructor, the base + destructor will perform the test. */ + + if (exprstmt != error_mark_node + && (TREE_CODE (exprstmt) != NOP_EXPR + || TREE_OPERAND (exprstmt, 0) != integer_zero_node + || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))) + { + expand_label (dtor_label); + if (cond != integer_one_node) + expand_start_cond (cond, 0); + if (exprstmt != void_zero_node) + /* Don't call `expand_expr_stmt' if we're not going to do + anything, since -Wall will give a diagnostic. */ + expand_expr_stmt (exprstmt); + + /* Run destructor on all virtual baseclasses. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + { + tree vbases = nreverse + (copy_list (CLASSTYPE_VBASECLASSES (current_class_type))); + expand_start_cond (build (BIT_AND_EXPR, integer_type_node, + in_charge_node, integer_two_node), 0); + while (vbases) + { + if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases))) + { + tree vb = get_vbase + (BINFO_TYPE (vbases), + TYPE_BINFO (current_class_type)); + + expand_expr_stmt + (build_base_dtor_call (current_class_ref, + vb, integer_zero_node)); + } + vbases = TREE_CHAIN (vbases); + } + expand_end_cond (); + } + + do_pending_stack_adjust (); + if (cond != integer_one_node) + expand_end_cond (); + } + + virtual_size = c_sizeof (current_class_type); + + /* At the end, call delete if that's what's requested. */ + + /* FDIS sez: At the point of definition of a virtual destructor + (including an implicit definition), non-placement operator + delete shall be looked up in the scope of the destructor's + class and if found shall be accessible and unambiguous. + + This is somewhat unclear, but I take it to mean that if the + class only defines placement deletes we don't do anything here. + So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain + for us if they ever try to delete one of these. */ + + if (TYPE_GETS_REG_DELETE (current_class_type) + || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + exprstmt = build_op_delete_call + (DELETE_EXPR, current_class_ptr, virtual_size, + LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE); + else + exprstmt = NULL_TREE; + + if (exprstmt) + { + cond = build (BIT_AND_EXPR, integer_type_node, + in_charge_node, integer_one_node); + expand_start_cond (cond, 0); + expand_expr_stmt (exprstmt); + expand_end_cond (); + } + + /* End of destructor. */ + expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0); + poplevel (getdecls () != NULL_TREE, 0, 0); + + /* Back to the top of destructor. */ + /* Don't execute destructor code if `this' is NULL. */ + + start_sequence (); + + /* If we need thunk-style vlists, initialize them if the caller did + not pass them. This requires a new temporary. The generated code + looks like + if (!(__in_charge & 4)) + __vlist = __vl. + sizeof(__vl.); + else + __vlist = __vlist1; + */ + if (TYPE_USES_PVBASES (current_class_type)) + { + tree vlist = lookup_name (vlist_identifier, 0); + tree vlist1 = lookup_name (get_identifier (VLIST1_NAME), 0); + cond = build (BIT_AND_EXPR, integer_type_node, + in_charge_node, build_int_2 (4, 0)); + cond = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond); + expand_start_cond (cond, 0); + init_vlist (current_class_type); + expand_start_else (); + expand_expr_stmt (build_modify_expr (vlist, NOP_EXPR, vlist1)); + expand_end_cond (); + } + + /* If the dtor is empty, and we know there is not possible way we + could use any vtable entries, before they are possibly set by + a base class dtor, we don't have to setup the vtables, as we + know that any base class dtoring will set up any vtables it + needs. We avoid MI, because one base class dtor can do a + virtual dispatch to an overridden function that would need to + have a non-related vtable set up, we cannot avoid setting up + vtables in that case. We could change this to see if there is + just one vtable. */ + if (! empty_dtor || TYPE_USES_COMPLEX_INHERITANCE (current_class_type)) + { + /* Make all virtual function table pointers in non-virtual base + classes point to CURRENT_CLASS_TYPE's virtual function + tables. */ + expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr); + + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + expand_indirect_vtbls_init (binfo, current_class_ref, current_class_ptr); + } + + if (! ok_to_optimize_dtor) + { + cond = build_binary_op (NE_EXPR, + current_class_ptr, integer_zero_node); + expand_start_cond (cond, 0); + } + + insns = get_insns (); + end_sequence (); + + last_parm_insn = get_first_nonparm_insn (); + if (last_parm_insn == NULL_RTX) + last_parm_insn = get_last_insn (); + else + last_parm_insn = previous_insn (last_parm_insn); + + emit_insns_after (insns, last_parm_insn); + + if (! ok_to_optimize_dtor) + expand_end_cond (); +} + +/* Emit implicit code for a constructor. This is a subroutine of + finish_function. CALL_POPLEVEL is the same variable in + finish_function. */ + +static void +finish_ctor (call_poplevel) + int call_poplevel; +{ + register tree fndecl = current_function_decl; + tree cond = NULL_TREE, thenclause = NULL_TREE; + rtx insns; + tree decls; + + /* Allow constructor for a type to get a new instance of the object + using `build_new'. */ + tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type); + CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE; + + if (flag_this_is_variable > 0) + { + cond = build_binary_op (EQ_EXPR, current_class_ptr, integer_zero_node); + thenclause = + build_modify_expr (current_class_ptr, NOP_EXPR, + build_new (NULL_TREE, current_class_type, + void_type_node, 0)); + } + + CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals; + + start_sequence (); + + if (flag_this_is_variable > 0) + { + expand_start_cond (cond, 0); + expand_expr_stmt (thenclause); + expand_end_cond (); + } + + /* Emit insns from `emit_base_init' which sets up virtual + function table pointer(s). */ + if (base_init_expr) + { + expand_expr_stmt (base_init_expr); + base_init_expr = NULL_TREE; + } + + insns = get_insns (); + end_sequence (); + + /* This is where the body of the constructor begins. */ + + emit_insns_after (insns, last_parm_cleanup_insn); + + end_protect_partials (); + + /* This is where the body of the constructor ends. */ + expand_label (ctor_label); + ctor_label = NULL_TREE; + + if (call_poplevel) + { + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); + poplevel (decls != NULL_TREE, 1, 0); + } + + /* c_expand_return knows to return 'this' from a constructor. */ + c_expand_return (NULL_TREE); + + current_function_assigns_this = 0; + current_function_just_assigned_this = 0; +} + + +/* Finish up a function declaration and compile that function + all the way to assembler language output. The free the storage + for the function definition. + + This is called after parsing the body of the function definition. + LINENO is the current line number. + + FLAGS is a bitwise or of the following values: + 1 - CALL_POPLEVEL + An extra call to poplevel (and expand_end_bindings) must be + made to take care of the binding contour for the base + initializers. This is only relevant for constructors. + 2 - INCLASS_INLINE + We just finished processing the body of an in-class inline + function definition. (This processing will have taken place + after the class definition is complete.) + + NESTED is nonzero if we were in the middle of compiling another function + when we started on this one. */ + +void +finish_function (lineno, flags, nested) + int lineno; + int flags; + int nested; +{ + register tree fndecl = current_function_decl; + tree fntype, ctype = NULL_TREE; + /* Label to use if this function is supposed to return a value. */ + tree no_return_label = NULL_TREE; + tree decls = NULL_TREE; + int call_poplevel = (flags & 1) != 0; + int inclass_inline = (flags & 2) != 0; + int in_template; + + /* When we get some parse errors, we can end up without a + current_function_decl, so cope. */ + if (fndecl == NULL_TREE) + return; + + if (function_depth > 1) + nested = 1; + + fntype = TREE_TYPE (fndecl); + +/* TREE_READONLY (fndecl) = 1; + This caused &foo to be of type ptr-to-const-function + which then got a warning when stored in a ptr-to-function variable. */ + + /* This happens on strange parse errors. */ + if (! current_function_parms_stored) + { + call_poplevel = 0; + store_parm_decls (); + } + + if (processing_template_decl) + { + if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel) + { + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); + poplevel (decls != NULL_TREE, 0, 0); + } + } + else + { + if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/) + { + tree ttype = target_type (fntype); + tree parmdecl; + + if (IS_AGGR_TYPE (ttype)) + /* Let debugger know it should output info for this type. */ + note_debug_info_needed (ttype); + + for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl)) + { + ttype = target_type (TREE_TYPE (parmdecl)); + if (IS_AGGR_TYPE (ttype)) + /* Let debugger know it should output info for this type. */ + note_debug_info_needed (ttype); + } + } + + /* Clean house because we will need to reorder insns here. */ + do_pending_stack_adjust (); + + if (dtor_label) + finish_dtor (); + else if (current_function_assigns_this) + { + /* Does not need to call emit_base_init, because + that is done (if needed) just after assignment to this + is seen. */ + + if (DECL_CONSTRUCTOR_P (current_function_decl)) + { + end_protect_partials (); + expand_label (ctor_label); + ctor_label = NULL_TREE; + + if (call_poplevel) + { + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); + poplevel (decls != NULL_TREE, 0, 0); + } + /* c_expand_return knows to return 'this' from a constructor. */ + c_expand_return (NULL_TREE); + } + else if (TREE_CODE (TREE_TYPE (DECL_RESULT (current_function_decl))) != VOID_TYPE + && return_label != NULL_RTX) + no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + + current_function_assigns_this = 0; + current_function_just_assigned_this = 0; + base_init_expr = NULL_TREE; + } + else if (DECL_CONSTRUCTOR_P (fndecl) + && !DECL_VLIST_CTOR_WRAPPER_P (fndecl)) + finish_ctor (call_poplevel); + else if (DECL_MAIN_P (fndecl)) + { + /* Make it so that `main' always returns 0 by default. */ +#ifdef VMS + c_expand_return (integer_one_node); +#else + c_expand_return (integer_zero_node); +#endif + } + else if (return_label != NULL_RTX + && current_function_return_value == NULL_TREE + && ! DECL_NAME (DECL_RESULT (current_function_decl))) + no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + + if (flag_exceptions) + expand_exception_blocks (); + + /* If this function is supposed to return a value, ensure that + we do not fall into the cleanups by mistake. The end of our + function will look like this: + + user code (may have return stmt somewhere) + goto no_return_label + cleanup_label: + cleanups + goto return_label + no_return_label: + NOTE_INSN_FUNCTION_END + return_label: + things for return + + If the user omits a return stmt in the USER CODE section, we + will have a control path which reaches NOTE_INSN_FUNCTION_END. + Otherwise, we won't. */ + if (no_return_label) + { + DECL_CONTEXT (no_return_label) = fndecl; + DECL_INITIAL (no_return_label) = error_mark_node; + DECL_SOURCE_FILE (no_return_label) = input_filename; + DECL_SOURCE_LINE (no_return_label) = lineno; + expand_goto (no_return_label); + } + + if (cleanup_label) + { + /* Remove the binding contour which is used + to catch cleanup-generated temporaries. */ + expand_end_bindings (0, 0, 0); + poplevel (0, 0, 0); + + /* Emit label at beginning of cleanup code for parameters. */ + emit_label (cleanup_label); + } + + /* Get return value into register if that's where it's supposed to be. */ + if (original_result_rtx) + fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx); + + /* Finish building code that will trigger warnings if users forget + to make their functions return values. */ + if (no_return_label || cleanup_label) + emit_jump (return_label); + if (no_return_label) + { + /* We don't need to call `expand_*_return' here because we + don't need any cleanups here--this path of code is only + for error checking purposes. */ + expand_label (no_return_label); + } + + /* Generate rtl for function exit. */ + expand_function_end (input_filename, lineno, 1); + } + + /* If we're processing a template, squirrel away the definition + until we do an instantiation. */ + if (processing_template_decl) + { + --minimal_parse_mode; + DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl)); + /* We have to save this value here in case + maybe_end_member_template_processing decides to pop all the + template parameters. */ + in_template = 1; + } + else + in_template = 0; + + /* This must come after expand_function_end because cleanups might + have declarations (from inline functions) that need to go into + this function's blocks. */ + if (current_binding_level->parm_flag != 1) + my_friendly_abort (122); + poplevel (1, 0, 1); + + /* If this is a in-class inline definition, we may have to pop the + bindings for the template parameters that we added in + maybe_begin_member_template_processing when start_function was + called. */ + if (inclass_inline) + maybe_end_member_template_processing (); + + /* Reset scope for C++: if we were in the scope of a class, + then when we finish this function, we are not longer so. + This cannot be done until we know for sure that no more + class members will ever be referenced in this function + (i.e., calls to destructors). */ + if (current_class_name) + { + ctype = current_class_type; + pop_nested_class (); + } + + /* Must mark the RESULT_DECL as being in this function. */ + DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl; + + /* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point + to the FUNCTION_DECL node itself. */ + BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; + + if (!in_template) + { + int saved_flag_keep_inline_functions = + flag_keep_inline_functions; + + /* So we can tell if jump_optimize sets it to 1. */ + can_reach_end = 0; + + if (DECL_CONTEXT (fndecl) != NULL_TREE + && hack_decl_function_context (fndecl)) + /* Trick rest_of_compilation into not deferring output of this + function, even if it is inline, since the rtl_obstack for + this function is the function_obstack of the enclosing + function and will be deallocated when the enclosing + function is gone. See save_tree_status. */ + flag_keep_inline_functions = 1; + + /* Run the optimizers and output the assembler code for this + function. */ + + if (DECL_ARTIFICIAL (fndecl)) + { + /* Do we really *want* to inline this synthesized method? */ + + int save_fif = flag_inline_functions; + flag_inline_functions = 1; + + /* Turn off DECL_INLINE for the moment so function_cannot_inline_p + will check our size. */ + DECL_INLINE (fndecl) = 0; + + rest_of_compilation (fndecl); + flag_inline_functions = save_fif; + } + else + rest_of_compilation (fndecl); + + flag_keep_inline_functions = saved_flag_keep_inline_functions; + + if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl)) + { + /* Set DECL_EXTERNAL so that assemble_external will be called as + necessary. We'll clear it again in finish_file. */ + if (! DECL_EXTERNAL (fndecl)) + DECL_NOT_REALLY_EXTERN (fndecl) = 1; + DECL_EXTERNAL (fndecl) = 1; + mark_inline_for_output (fndecl); + } + + if (ctype && TREE_ASM_WRITTEN (fndecl)) + note_debug_info_needed (ctype); + + current_function_returns_null |= can_reach_end; + + /* Since we don't normally go through c_expand_return for constructors, + this normally gets the wrong value. + Also, named return values have their return codes emitted after + NOTE_INSN_FUNCTION_END, confusing jump.c. */ + if (DECL_CONSTRUCTOR_P (fndecl) + || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE) + current_function_returns_null = 0; + + if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null) + cp_warning ("`noreturn' function `%D' does return", fndecl); + else if ((warn_return_type || pedantic) + && current_function_returns_null + && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE) + { + /* If this function returns non-void and control can drop through, + complain. */ + cp_warning ("control reaches end of non-void function `%D'", fndecl); + } + /* With just -W, complain only if function returns both with + and without a value. */ + else if (extra_warnings + && current_function_returns_value && current_function_returns_null) + warning ("this function may return with or without a value"); + } + + --function_depth; + + /* Free all the tree nodes making up this function. */ + /* Switch back to allocating nodes permanently + until we start another function. */ + if (! nested) + permanent_allocation (1); + + if (DECL_SAVED_INSNS (fndecl) == NULL_RTX) + { + tree t; + + /* Stop pointing to the local nodes about to be freed. */ + /* But DECL_INITIAL must remain nonzero so we know this + was an actual function definition. */ + DECL_INITIAL (fndecl) = error_mark_node; + for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) + DECL_RTL (t) = DECL_INCOMING_RTL (t) = NULL_RTX; + } + + if (DECL_STATIC_CONSTRUCTOR (fndecl)) + static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors); + if (DECL_STATIC_DESTRUCTOR (fndecl)) + static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors); + + if (! nested) + { + /* Let the error reporting routines know that we're outside a + function. For a nested function, this value is used in + pop_cp_function_context and then reset via pop_function_context. */ + current_function_decl = NULL_TREE; + } + + named_label_uses = NULL; + current_class_ptr = NULL_TREE; + current_class_ref = NULL_TREE; +} + +/* Create the FUNCTION_DECL for a function definition. + DECLSPECS and DECLARATOR are the parts of the declaration; + they describe the return type and the name of the function, + but twisted together in a fashion that parallels the syntax of C. + + This function creates a binding context for the function body + as well as setting up the FUNCTION_DECL in current_function_decl. + + Returns a FUNCTION_DECL on success. + + If the DECLARATOR is not suitable for a function (it defines a datum + instead), we return 0, which tells yyparse to report a parse error. + + May return void_type_node indicating that this method is actually + a friend. See grokfield for more details. + + Came here with a `.pushlevel' . + + DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING + CHANGES TO CODE IN `grokfield'. */ + +tree +start_method (declspecs, declarator, attrlist) + tree declarator, declspecs, attrlist; +{ + tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, + attrlist); + + /* Something too ugly to handle. */ + if (fndecl == NULL_TREE) + return NULL_TREE; + + /* Pass friends other than inline friend functions back. */ + if (fndecl == void_type_node) + return fndecl; + + if (TREE_CODE (fndecl) != FUNCTION_DECL) + /* Not a function, tell parser to report parse error. */ + return NULL_TREE; + + if (IS_SIGNATURE (current_class_type)) + IS_DEFAULT_IMPLEMENTATION (fndecl) = 1; + + if (DECL_IN_AGGR_P (fndecl)) + { + if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type) + { + if (DECL_CONTEXT (fndecl) + && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL) + cp_error ("`%D' is already defined in class %s", fndecl, + TYPE_NAME_STRING (DECL_CONTEXT (fndecl))); + } + return void_type_node; + } + + check_template_shadow (fndecl); + + DECL_THIS_INLINE (fndecl) = 1; + + if (flag_default_inline) + DECL_INLINE (fndecl) = 1; + + /* We process method specializations in finish_struct_1. */ + if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl)) + fndecl = push_template_decl (fndecl); + + /* We read in the parameters on the maybepermanent_obstack, + but we won't be getting back to them until after we + may have clobbered them. So the call to preserve_data + will keep them safe. */ + preserve_data (); + + if (! DECL_FRIEND_P (fndecl)) + { + if (TREE_CHAIN (fndecl)) + { + fndecl = copy_node (fndecl); + TREE_CHAIN (fndecl) = NULL_TREE; + } + + if (DECL_CONSTRUCTOR_P (fndecl)) + { + if (! grok_ctor_properties (current_class_type, fndecl)) + return void_type_node; + } + else if (IDENTIFIER_OPNAME_P (DECL_NAME (fndecl))) + grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl), 0); + } + + cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0, 0); + + /* Make a place for the parms */ + pushlevel (0); + current_binding_level->parm_flag = 1; + + DECL_IN_AGGR_P (fndecl) = 1; + return fndecl; +} + +/* Go through the motions of finishing a function definition. + We don't compile this method until after the whole class has + been processed. + + FINISH_METHOD must return something that looks as though it + came from GROKFIELD (since we are defining a method, after all). + + This is called after parsing the body of the function definition. + STMTS is the chain of statements that makes up the function body. + + DECL is the ..._DECL that `start_method' provided. */ + +tree +finish_method (decl) + tree decl; +{ + register tree fndecl = decl; + tree old_initial; + + register tree link; + + if (decl == void_type_node) + return decl; + + old_initial = DECL_INITIAL (fndecl); + + /* Undo the level for the parms (from start_method). + This is like poplevel, but it causes nothing to be + saved. Saving information here confuses symbol-table + output routines. Besides, this information will + be correctly output when this method is actually + compiled. */ + + /* Clear out the meanings of the local variables of this level; + also record in each decl which block it belongs to. */ + + for (link = current_binding_level->names; link; link = TREE_CHAIN (link)) + { + if (DECL_NAME (link) != NULL_TREE) + pop_binding (DECL_NAME (link), link); + my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163); + DECL_CONTEXT (link) = NULL_TREE; + } + + GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level, + (HOST_WIDE_INT) current_binding_level->level_chain, + current_binding_level->parm_flag, + current_binding_level->keep); + + poplevel (0, 0, 0); + + DECL_INITIAL (fndecl) = old_initial; + + /* We used to check if the context of FNDECL was different from + current_class_type as another way to get inside here. This didn't work + for String.cc in libg++. */ + if (DECL_FRIEND_P (fndecl)) + { + CLASSTYPE_INLINE_FRIENDS (current_class_type) + = tree_cons (NULL_TREE, fndecl, CLASSTYPE_INLINE_FRIENDS (current_class_type)); + decl = void_type_node; + } + + return decl; +} + +/* Called when a new struct TYPE is defined. + If this structure or union completes the type of any previous + variable declaration, lay it out and output its rtl. */ + +void +hack_incomplete_structures (type) + tree type; +{ + tree *list; + + if (current_binding_level->incomplete == NULL_TREE) + return; + + if (!type) /* Don't do this for class templates. */ + return; + + for (list = ¤t_binding_level->incomplete; *list; ) + { + tree decl = TREE_VALUE (*list); + if ((decl && TREE_TYPE (decl) == type) + || (TREE_TYPE (decl) + && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && TREE_TYPE (TREE_TYPE (decl)) == type)) + { + int toplevel = toplevel_bindings_p (); + if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && TREE_TYPE (TREE_TYPE (decl)) == type) + layout_type (TREE_TYPE (decl)); + layout_decl (decl, 0); + rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0); + if (! toplevel) + { + tree cleanup; + expand_decl (decl); + cleanup = maybe_build_cleanup (decl); + expand_decl_init (decl); + if (! expand_decl_cleanup (decl, cleanup)) + cp_error ("parser lost in parsing declaration of `%D'", + decl); + } + *list = TREE_CHAIN (*list); + } + else + list = &TREE_CHAIN (*list); + } +} + +/* If DECL is of a type which needs a cleanup, build that cleanup here. + See build_delete for information about AUTO_DELETE. + + Don't build these on the momentary obstack; they must live + the life of the binding contour. */ + +static tree +maybe_build_cleanup_1 (decl, auto_delete) + tree decl, auto_delete; +{ + tree type = TREE_TYPE (decl); + if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type)) + { + int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR; + tree rval; + + if (TREE_CODE (decl) != PARM_DECL) + temp = suspend_momentary (); + + if (TREE_CODE (type) == ARRAY_TYPE) + rval = decl; + else + { + mark_addressable (decl); + rval = build_unary_op (ADDR_EXPR, decl, 0); + } + + /* Optimize for space over speed here. */ + if (! TYPE_USES_VIRTUAL_BASECLASSES (type) + || flag_expensive_optimizations) + flags |= LOOKUP_NONVIRTUAL; + + rval = build_delete (TREE_TYPE (rval), rval, auto_delete, flags, 0); + + if (TYPE_USES_VIRTUAL_BASECLASSES (type) + && ! TYPE_HAS_DESTRUCTOR (type)) + rval = build_compound_expr (expr_tree_cons (NULL_TREE, rval, + build_expr_list (NULL_TREE, build_vbase_delete (type, decl)))); + + if (TREE_CODE (decl) != PARM_DECL) + resume_momentary (temp); + + return rval; + } + return 0; +} + +/* If DECL is of a type which needs a cleanup, build that cleanup + here. The cleanup does free the storage with a call to delete. */ + +tree +maybe_build_cleanup_and_delete (decl) + tree decl; +{ + return maybe_build_cleanup_1 (decl, integer_three_node); +} + +/* If DECL is of a type which needs a cleanup, build that cleanup + here. The cleanup does not free the storage with a call a delete. */ + +tree +maybe_build_cleanup (decl) + tree decl; +{ + return maybe_build_cleanup_1 (decl, integer_two_node); +} + +/* Expand a C++ expression at the statement level. + This is needed to ferret out nodes which have UNKNOWN_TYPE. + The C++ type checker should get all of these out when + expressions are combined with other, type-providing, expressions, + leaving only orphan expressions, such as: + + &class::bar; / / takes its address, but does nothing with it. */ + +void +cplus_expand_expr_stmt (exp) + tree exp; +{ + if (processing_template_decl) + { + add_tree (build_min_nt (EXPR_STMT, exp)); + return; + } + + /* Arrange for all temps to disappear. */ + expand_start_target_temps (); + + exp = require_complete_type_in_void (exp); + + if (TREE_CODE (exp) == FUNCTION_DECL) + { + cp_warning ("reference, not call, to function `%D'", exp); + warning ("at this point in file"); + } + +#if 0 + /* We should do this eventually, but right now this causes regex.o from + libg++ to miscompile, and tString to core dump. */ + exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp); +#endif + + /* Strip unused implicit INDIRECT_REFs of references. */ + if (TREE_CODE (exp) == INDIRECT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE) + exp = TREE_OPERAND (exp, 0); + + /* If we don't do this, we end up down inside expand_expr + trying to do TYPE_MODE on the ERROR_MARK, and really + go outside the bounds of the type. */ + if (exp != error_mark_node) + expand_expr_stmt (break_out_cleanups (exp)); + + /* Clean up any pending cleanups. This happens when a function call + returns a cleanup-needing value that nobody uses. */ + expand_end_target_temps (); +} + +/* When a stmt has been parsed, this function is called. + + Currently, this function only does something within a + constructor's scope: if a stmt has just assigned to this, + and we are in a derived class, we call `emit_base_init'. */ + +void +finish_stmt () +{ + extern struct nesting *cond_stack, *loop_stack, *case_stack; + + + if (current_function_assigns_this + || ! current_function_just_assigned_this) + return; + if (DECL_CONSTRUCTOR_P (current_function_decl)) + { + /* Constructors must wait until we are out of control + zones before calling base constructors. */ + if (cond_stack || loop_stack || case_stack) + return; + expand_expr_stmt (base_init_expr); + check_base_init (current_class_type); + } + current_function_assigns_this = 1; +} + +/* Change a static member function definition into a FUNCTION_TYPE, instead + of the METHOD_TYPE that we create when it's originally parsed. + + WARNING: DO NOT pass &TREE_TYPE (decl) to FN or &TYPE_ARG_TYPES + (TREE_TYPE (decl)) to ARGTYPES, as doing so will corrupt the types of + other decls. Either pass the addresses of local variables or NULL. */ + +void +revert_static_member_fn (decl, fn, argtypes) + tree *decl, *fn, *argtypes; +{ + tree tmp; + tree function = fn ? *fn : TREE_TYPE (*decl); + tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function); + + if (CP_TYPE_QUALS (TREE_TYPE (TREE_VALUE (args))) + != TYPE_UNQUALIFIED) + cp_error ("static member function `%#D' declared with type qualifiers", + *decl); + + args = TREE_CHAIN (args); + tmp = build_function_type (TREE_TYPE (function), args); + tmp = build_qualified_type (tmp, CP_TYPE_QUALS (function)); + tmp = build_exception_variant (tmp, + TYPE_RAISES_EXCEPTIONS (function)); + TREE_TYPE (*decl) = tmp; + if (DECL_ARGUMENTS (*decl)) + DECL_ARGUMENTS (*decl) = TREE_CHAIN (DECL_ARGUMENTS (*decl)); + DECL_STATIC_FUNCTION_P (*decl) = 1; + if (fn) + *fn = tmp; + if (argtypes) + *argtypes = args; +} + +struct cp_function +{ + int returns_value; + int returns_null; + int assigns_this; + int just_assigned_this; + int parms_stored; + int temp_name_counter; + tree named_labels; + struct named_label_list *named_label_uses; + tree shadowed_labels; + tree ctor_label; + tree dtor_label; + rtx last_dtor_insn; + rtx last_parm_cleanup_insn; + tree base_init_list; + tree member_init_list; + tree base_init_expr; + tree current_class_ptr; + tree current_class_ref; + rtx result_rtx; + struct cp_function *next; + struct binding_level *binding_level; + int static_labelno; +}; + +static struct cp_function *cp_function_chain; + +extern int temp_name_counter; + +/* Save and reinitialize the variables + used during compilation of a C++ function. */ + +void +push_cp_function_context (context) + tree context; +{ + struct cp_function *p + = (struct cp_function *) xmalloc (sizeof (struct cp_function)); + + push_function_context_to (context); + + p->next = cp_function_chain; + cp_function_chain = p; + + p->named_labels = named_labels; + p->named_label_uses = named_label_uses; + p->shadowed_labels = shadowed_labels; + p->returns_value = current_function_returns_value; + p->returns_null = current_function_returns_null; + p->binding_level = current_binding_level; + p->ctor_label = ctor_label; + p->dtor_label = dtor_label; + p->last_dtor_insn = last_dtor_insn; + p->last_parm_cleanup_insn = last_parm_cleanup_insn; + p->assigns_this = current_function_assigns_this; + p->just_assigned_this = current_function_just_assigned_this; + p->parms_stored = current_function_parms_stored; + p->result_rtx = original_result_rtx; + p->base_init_expr = base_init_expr; + p->temp_name_counter = temp_name_counter; + p->base_init_list = current_base_init_list; + p->member_init_list = current_member_init_list; + p->current_class_ptr = current_class_ptr; + p->current_class_ref = current_class_ref; + p->static_labelno = static_labelno; +} + +/* Restore the variables used during compilation of a C++ function. */ + +void +pop_cp_function_context (context) + tree context; +{ + struct cp_function *p = cp_function_chain; + tree link; + + /* Bring back all the labels that were shadowed. */ + for (link = shadowed_labels; link; link = TREE_CHAIN (link)) + if (DECL_NAME (TREE_VALUE (link)) != 0) + SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)), + TREE_VALUE (link)); + + pop_function_context_from (context); + + cp_function_chain = p->next; + + named_labels = p->named_labels; + named_label_uses = p->named_label_uses; + shadowed_labels = p->shadowed_labels; + current_function_returns_value = p->returns_value; + current_function_returns_null = p->returns_null; + current_binding_level = p->binding_level; + ctor_label = p->ctor_label; + dtor_label = p->dtor_label; + last_dtor_insn = p->last_dtor_insn; + last_parm_cleanup_insn = p->last_parm_cleanup_insn; + current_function_assigns_this = p->assigns_this; + current_function_just_assigned_this = p->just_assigned_this; + current_function_parms_stored = p->parms_stored; + original_result_rtx = p->result_rtx; + base_init_expr = p->base_init_expr; + temp_name_counter = p->temp_name_counter; + current_base_init_list = p->base_init_list; + current_member_init_list = p->member_init_list; + current_class_ptr = p->current_class_ptr; + current_class_ref = p->current_class_ref; + static_labelno = p->static_labelno; + + free (p); +} + +int +in_function_p () +{ + return function_depth != 0; +} Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/decl.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/decl2.c =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/decl2.c (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/decl2.c (revision 60969) @@ -0,0 +1,5379 @@ +/* Process declarations and variables for C compiler. + Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc. + Hacked by Michael Tiemann (tiemann@cygnus.com) + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +/* Process declarations and symbol lookup for C front end. + Also constructs types; the standard scalar types at initialization, + and structure, union, array and enum types when they are declared. */ + +/* ??? not all decl nodes are given the most useful possible + line numbers. For example, the CONST_DECLs for enum values. */ + +#include "config.h" +#include "system.h" +#include "tree.h" +#include "rtl.h" +#include "flags.h" +#include "cp-tree.h" +#include "decl.h" +#include "lex.h" +#include "output.h" +#include "except.h" +#include "expr.h" +#include "defaults.h" +#include "toplev.h" +#include "dwarf2out.h" +#include "dwarfout.h" +#include "splay-tree.h" +#include "varray.h" + +#if USE_CPPLIB +#include "cpplib.h" +extern cpp_reader parse_in; +#endif + +/* This structure contains information about the initializations + and/or destructions required for a particular priority level. */ +typedef struct priority_info_s { + /* A label indicating where we should generate the next + initialization with this priority. */ + rtx initialization_sequence; + /* A label indicating where we should generate the next destruction + with this priority. */ + rtx destruction_sequence; + /* Non-zero if there have been any initializations at this priority + throughout the translation unit. */ + int initializations_p; + /* Non-zero if there have been any destructions at this priority + throughout the translation unit. */ + int destructions_p; +} *priority_info; + +static tree get_sentry PROTO((tree)); +static void mark_vtable_entries PROTO((tree)); +static void grok_function_init PROTO((tree, tree)); +static int finish_vtable_vardecl PROTO((tree *, void *)); +static int prune_vtable_vardecl PROTO((tree *, void *)); +static int finish_sigtable_vardecl PROTO((tree *, void *)); +static int is_namespace_ancestor PROTO((tree, tree)); +static void add_using_namespace PROTO((tree, tree, int)); +static tree ambiguous_decl PROTO((tree, tree, tree,int)); +static tree build_anon_union_vars PROTO((tree, tree*, int, int)); +static int acceptable_java_type PROTO((tree)); +static void output_vtable_inherit PROTO((tree)); +static void start_objects PROTO((int, int)); +static void finish_objects PROTO((int, int)); +static tree merge_functions PROTO((tree, tree)); +static tree decl_namespace PROTO((tree)); +static tree validate_nonmember_using_decl PROTO((tree, tree *, tree *)); +static void do_nonmember_using_decl PROTO((tree, tree, tree, tree, + tree *, tree *)); +static void start_static_storage_duration_function PROTO((void)); +static int generate_inits_for_priority PROTO((splay_tree_node, void *)); +static void finish_static_storage_duration_function PROTO((void)); +static priority_info get_priority_info PROTO((int)); +static void do_static_initialization PROTO((tree, tree, tree, int)); +static void do_static_destruction PROTO((tree, tree, int)); +static void do_static_initialization_and_destruction PROTO((tree, tree)); +static void generate_ctor_or_dtor_function PROTO((int, int)); +static int generate_ctor_and_dtor_functions_for_priority + PROTO((splay_tree_node, void *)); +extern int current_class_depth; + +/* A list of virtual function tables we must make sure to write out. */ +tree pending_vtables; + +/* A list of static class variables. This is needed, because a + static class variable can be declared inside the class without + an initializer, and then initialized, staticly, outside the class. */ +static varray_type pending_statics; +static size_t pending_statics_used; + +/* A list of functions which were declared inline, but which we + may need to emit outline anyway. */ +static varray_type saved_inlines; +static size_t saved_inlines_used; + +/* Used to help generate temporary names which are unique within + a function. Reset to 0 by start_function. */ + +int temp_name_counter; + +/* Same, but not reset. Local temp variables and global temp variables + can have the same name. */ +static int global_temp_name_counter; + +/* Flag used when debugging spew.c */ + +extern int spew_debug; + +/* Nonzero if we're done parsing and into end-of-file activities. */ + +int at_eof; + +/* Functions called along with real static constructors and destructors. */ + +tree static_ctors, static_dtors; + +/* The current open namespace, and ::. */ + +tree current_namespace; +tree global_namespace; + +/* The stack for namespaces of current declarations. */ + +static tree decl_namespace_list; + + +/* C (and C++) language-specific option variables. */ + +/* Nonzero means allow type mismatches in conditional expressions; + just make their values `void'. */ + +int flag_cond_mismatch; + +/* Nonzero means give `double' the same size as `float'. */ + +int flag_short_double; + +/* Nonzero means don't recognize the keyword `asm'. */ + +int flag_no_asm; + +/* Nonzero means don't recognize any extension keywords. */ + +int flag_no_gnu_keywords; + +/* Nonzero means don't recognize the non-ANSI builtin functions. */ + +int flag_no_builtin; + +/* Nonzero means don't recognize the non-ANSI builtin functions. + -ansi sets this. */ + +int flag_no_nonansi_builtin; + +/* Nonzero means do some things the same way PCC does. Only provided so + the compiler will link. */ + +int flag_traditional; + +/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */ + +int flag_signed_bitfields = 1; + +/* Nonzero means enable obscure ANSI features and disable GNU extensions + that might cause ANSI-compliant code to be miscompiled. */ + +int flag_ansi; + +/* Nonzero means do emit exported implementations of functions even if + they can be inlined. */ + +int flag_implement_inlines = 1; + +/* Nonzero means do emit exported implementations of templates, instead of + multiple static copies in each file that needs a definition. */ + +int flag_external_templates; + +/* Nonzero means that the decision to emit or not emit the implementation of a + template depends on where the template is instantiated, rather than where + it is defined. */ + +int flag_alt_external_templates; + +/* Nonzero means that implicit instantiations will be emitted if needed. */ + +int flag_implicit_templates = 1; + +/* Nonzero means that implicit instantiations of inline templates will be + emitted if needed, even if instantiations of non-inline templates + aren't. */ + +int flag_implicit_inline_templates = 1; + +/* Nonzero means warn about implicit declarations. */ + +int warn_implicit = 1; + +/* Nonzero means warn about usage of long long when `-pedantic'. */ + +int warn_long_long = 1; + +/* Nonzero means warn when all ctors or dtors are private, and the class + has no friends. */ + +int warn_ctor_dtor_privacy = 1; + +/* 1 or 2 if we want to implement vtables using "thunks". + The default is off. Version 1 indicates "old" implementation; + Version 2 passes the __vlist argument in pvbase cases. */ + +#ifndef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 0 +#endif +int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS; + +#if DEFAULT_VTABLE_THUNKS == 2 +int flag_vtable_thunks_compat = 1; +#else +int flag_vtable_thunks_compat = 0; +#endif + +/* True if we want to deal with repository information. */ + +int flag_use_repository; + +/* Nonzero if we want to issue diagnostics that the standard says are not + required. */ + +int flag_optional_diags = 1; + +/* Nonzero means give string constants the type `const char *', as mandated + by the standard. */ + +int flag_const_strings = 1; + +/* Nonzero means warn about deprecated conversion from string constant to + `char *'. */ + +int warn_write_strings; + +/* Nonzero means warn about pointer casts that can drop a type qualifier + from the pointer target type. */ + +int warn_cast_qual; + +/* Nonzero means warn about sizeof(function) or addition/subtraction + of function pointers. */ + +int warn_pointer_arith = 1; + +/* Nonzero means warn for any function def without prototype decl. */ + +int warn_missing_prototypes; + +/* Nonzero means warn about multiple (redundant) decls for the same single + variable or function. */ + +int warn_redundant_decls; + +/* Warn if initializer is not completely bracketed. */ + +int warn_missing_braces; + +/* Warn about comparison of signed and unsigned values. */ + +int warn_sign_compare; + +/* Warn about *printf or *scanf format/argument anomalies. */ + +int warn_format; + +/* Warn about a subscript that has type char. */ + +int warn_char_subscripts; + +/* Warn if a type conversion is done that might have confusing results. */ + +int warn_conversion; + +/* Warn if adding () is suggested. */ + +int warn_parentheses; + +/* Non-zero means warn in function declared in derived class has the + same name as a virtual in the base class, but fails to match the + type signature of any virtual function in the base class. */ +int warn_overloaded_virtual; + +/* Non-zero means warn when declaring a class that has a non virtual + destructor, when it really ought to have a virtual one. */ +int warn_nonvdtor; + +/* Non-zero means warn when a function is declared extern and later inline. */ +int warn_extern_inline; + +/* Non-zero means warn when the compiler will reorder code. */ +int warn_reorder; + +/* Non-zero means warn when synthesis behavior differs from Cfront's. */ +int warn_synth; + +/* Non-zero means warn when we convert a pointer to member function + into a pointer to (void or function). */ +int warn_pmf2ptr = 1; + +/* Nonzero means warn about violation of some Effective C++ style rules. */ + +int warn_ecpp; + +/* Nonzero means warn where overload resolution chooses a promotion from + unsigned to signed over a conversion to an unsigned of the same size. */ + +int warn_sign_promo; + +/* Nonzero means warn when an old-style cast is used. */ + +int warn_old_style_cast; + +/* Warn about #pragma directives that are not recognised. */ + +int warn_unknown_pragmas; /* Tri state variable. */ + +/* Nonzero means warn about use of multicharacter literals. */ + +int warn_multichar = 1; + +/* Nonzero means warn when non-templatized friend functions are + declared within a template */ + +int warn_nontemplate_friend = 1; + +/* Nonzero means complain about deprecated features. */ + +int warn_deprecated = 1; + +/* Nonzero means `$' can be in an identifier. */ + +#ifndef DOLLARS_IN_IDENTIFIERS +#define DOLLARS_IN_IDENTIFIERS 1 +#endif +int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; + +/* Nonzero for -fno-strict-prototype switch: do not consider empty + argument prototype to mean function takes no arguments. */ + +int flag_strict_prototype = 2; +int strict_prototype = 1; +int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus = 1; + +/* Nonzero means that labels can be used as first-class objects */ + +int flag_labels_ok; + +/* Non-zero means to collect statistics which might be expensive + and to print them when we are done. */ +int flag_detailed_statistics; + +/* C++ specific flags. */ +/* Zero means that `this' is a *const. This gives nice behavior in the + 2.0 world. 1 gives 1.2-compatible behavior. 2 gives Spring behavior. + -2 means we're constructing an object and it has fixed type. */ + +int flag_this_is_variable; + +/* 3 means write out only virtuals function tables `defined' + in this implementation file. + 0 means write out virtual function tables and give them + (C) static access (default). */ + +int write_virtuals; + +/* Nonzero means we should attempt to elide constructors when possible. */ + +int flag_elide_constructors = 1; + +/* Nonzero means recognize and handle signature language constructs. */ + +int flag_handle_signatures; + +/* Nonzero means that member functions defined in class scope are + inline by default. */ + +int flag_default_inline = 1; + +/* Controls whether compiler generates 'type descriptor' that give + run-time type information. */ +int flag_rtti = 1; + +/* Nonzero if we wish to output cross-referencing information + for the GNU class browser. */ +extern int flag_gnu_xref; + +/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes) + objects. */ + +int flag_huge_objects; + +/* Nonzero if we want to conserve space in the .o files. We do this + by putting uninitialized data and runtime initialized data into + .common instead of .data at the expense of not flagging multiple + definitions. */ + +int flag_conserve_space; + +/* Nonzero if we want to obey access control semantics. */ + +int flag_access_control = 1; + +/* Nonzero if we want to understand the operator names, i.e. 'bitand'. */ + +int flag_operator_names; + +/* Nonzero if we want to check the return value of new and avoid calling + constructors if it is a null pointer. */ + +int flag_check_new; + +/* Nonzero if we want the new ANSI rules for pushing a new scope for `for' + initialization variables. + 0: Old rules, set by -fno-for-scope. + 2: New ANSI rules, set by -ffor-scope. + 1: Try to implement new ANSI rules, but with backup compatibility + (and warnings). This is the default, for now. */ + +int flag_new_for_scope = 1; + +/* Nonzero if we want to emit defined symbols with common-like linkage as + weak symbols where possible, in order to conform to C++ semantics. + Otherwise, emit them as local symbols. */ + +int flag_weak = 1; + +/* Nonzero to enable experimental ABI changes. */ + +int flag_new_abi; + +/* Nonzero to not ignore namespace std. */ + +int flag_honor_std; + +/* Maximum template instantiation depth. Must be at least 17 for ANSI + compliance. */ + +int max_tinst_depth = 17; + +/* The name-mangling scheme to use. Must be 1 or greater to support + template functions with identical types, but different template + arguments. */ +int name_mangling_version = 2; + +/* Nonzero means that guiding declarations are allowed. */ +int flag_guiding_decls; + +/* Nonzero if squashed mangling is to be performed. + This uses the B and K codes to reference previously seen class types + and class qualifiers. */ +int flag_do_squangling; + +/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */ + +int flag_vtable_gc; + +/* Nonzero means make the default pedwarns warnings instead of errors. + The value of this flag is ignored if -pedantic is specified. */ + +int flag_permissive; + +/* Table of language-dependent -f options. + STRING is the option name. VARIABLE is the address of the variable. + ON_VALUE is the value to store in VARIABLE + if `-fSTRING' is seen as an option. + (If `-fno-STRING' is seen as an option, the opposite value is stored.) */ + +static struct { const char *string; int *variable; int on_value;} +lang_f_options[] = +{ + /* C/C++ options. */ + {"signed-char", &flag_signed_char, 1}, + {"unsigned-char", &flag_signed_char, 0}, + {"signed-bitfields", &flag_signed_bitfields, 1}, + {"unsigned-bitfields", &flag_signed_bitfields, 0}, + {"short-enums", &flag_short_enums, 1}, + {"short-double", &flag_short_double, 1}, + {"cond-mismatch", &flag_cond_mismatch, 1}, + {"asm", &flag_no_asm, 0}, + {"builtin", &flag_no_builtin, 0}, + + /* C++-only options. */ + {"access-control", &flag_access_control, 1}, + {"check-new", &flag_check_new, 1}, + {"conserve-space", &flag_conserve_space, 1}, + {"const-strings", &flag_const_strings, 1}, + {"default-inline", &flag_default_inline, 1}, + {"dollars-in-identifiers", &dollars_in_ident, 1}, + {"elide-constructors", &flag_elide_constructors, 1}, + {"external-templates", &flag_external_templates, 1}, + {"for-scope", &flag_new_for_scope, 2}, + {"gnu-keywords", &flag_no_gnu_keywords, 0}, + {"handle-exceptions", &flag_exceptions, 1}, + {"handle-signatures", &flag_handle_signatures, 1}, + {"honor-std", &flag_honor_std, 1}, + {"huge-objects", &flag_huge_objects, 1}, + {"implement-inlines", &flag_implement_inlines, 1}, + {"implicit-inline-templates", &flag_implicit_inline_templates, 1}, + {"implicit-templates", &flag_implicit_templates, 1}, + {"labels-ok", &flag_labels_ok, 1}, + {"nonansi-builtins", &flag_no_nonansi_builtin, 0}, + {"operator-names", &flag_operator_names, 1}, + {"optional-diags", &flag_optional_diags, 1}, + {"permissive", &flag_permissive, 1}, + {"repo", &flag_use_repository, 1}, + {"rtti", &flag_rtti, 1}, + {"squangle", &flag_do_squangling, 1}, + {"stats", &flag_detailed_statistics, 1}, + {"strict-prototype", &flag_strict_prototype, 1}, + {"this-is-variable", &flag_this_is_variable, 1}, + {"vtable-gc", &flag_vtable_gc, 1}, + {"vtable-thunks", &flag_vtable_thunks, 1}, + {"weak", &flag_weak, 1}, + {"xref", &flag_gnu_xref, 1} +}; + +/* Decode the string P as a language-specific option. + Return the number of strings consumed for a valid option. + Otherwise return 0. */ + +int +lang_decode_option (argc, argv) + int argc +#if !USE_CPPLIB + ATTRIBUTE_UNUSED +#endif + ; + char **argv; + +{ + int strings_processed; + char *p = argv[0]; +#if USE_CPPLIB + strings_processed = cpp_handle_option (&parse_in, argc, argv); +#else + strings_processed = 0; +#endif /* ! USE_CPPLIB */ + + if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional")) + /* ignore */; + else if (p[0] == '-' && p[1] == 'f') + { + /* Some kind of -f option. + P's value is the option sans `-f'. + Search for it in the table of options. */ + int found = 0; + size_t j; + + p += 2; + /* Try special -f options. */ + + if (!strcmp (p, "handle-exceptions") + || !strcmp (p, "no-handle-exceptions")) + warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)"); + + if (!strcmp (p, "memoize-lookups") + || !strcmp (p, "no-memoize-lookups") + || !strcmp (p, "save-memoized") + || !strcmp (p, "no-save-memoized") + || !strcmp (p, "no-all-virtual") + || !strcmp (p, "no-enum-int-equiv") + || !strcmp (p, "nonnull-objects") + || !strcmp (p, "ansi-overloading")) + { + /* ignore */ + found = 1; + } + else if (!strcmp (p, "all-virtual") + || !strcmp (p, "enum-int-equiv") + || !strcmp (p, "no-nonnull-objects") + || !strcmp (p, "no-ansi-overloading")) + { + warning ("-f%s is no longer supported", p); + found = 1; + } + else if (! strcmp (p, "alt-external-templates")) + { + flag_external_templates = 1; + flag_alt_external_templates = 1; + found = 1; + cp_deprecated ("-falt-external-templates"); + } + else if (! strcmp (p, "no-alt-external-templates")) + { + flag_alt_external_templates = 0; + found = 1; + } + else if (!strcmp (p, "repo")) + { + flag_use_repository = 1; + flag_implicit_templates = 0; + found = 1; + } + else if (!strcmp (p, "guiding-decls")) + { + flag_guiding_decls = 1; + name_mangling_version = 0; + found = 1; + } + else if (!strcmp (p, "no-guiding-decls")) + { + flag_guiding_decls = 0; + found = 1; + } + else if (!strcmp (p, "this-is-variable")) + { + flag_this_is_variable = 1; + found = 1; + cp_deprecated ("-fthis-is-variable"); + } + else if (!strcmp (p, "external-templates")) + { + flag_external_templates = 1; + found = 1; + cp_deprecated ("-fexternal-templates"); + } + else if (!strncmp (p, "vtable-thunks", 13)) + { + if (p[13] == '=') + { + flag_vtable_thunks = + read_integral_parameter (p+14, p, 1); + } + else + { + /* If the machine file has a default setting, use that + for -fvtable-thunks. Otherwise, set it to version + 2. */ +#if DEFAULT_VTABLE_THUNKS + flag_vtable_thunks = DEFAULT_VTABLE_THUNKS; +#else + flag_vtable_thunks = 1; +#endif + } + if (flag_vtable_thunks == 2) + /* v2 is a compatibility mode between v1 and v3. */ + flag_vtable_thunks_compat = 1; + else if(flag_vtable_thunks == 3) + flag_vtable_thunks_compat = 0; + found = 1; + } + else if (!strcmp (p, "handle-signatures")) + { + flag_handle_signatures = 1; + found = 1; + cp_deprecated ("-fhandle-signatures"); + } + else if (!strcmp (p, "new-abi")) + { + flag_new_abi = 1; + flag_do_squangling = 1; + flag_honor_std = 1; + flag_vtable_thunks = 2; + } + else if (!strcmp (p, "no-new-abi")) + { + flag_new_abi = 0; + flag_do_squangling = 0; + flag_honor_std = 0; + } + else if (!strncmp (p, "template-depth-", 15)) + { + max_tinst_depth = + read_integral_parameter (p + 15, p - 2, max_tinst_depth); + } + else if (!strncmp (p, "name-mangling-version-", 22)) + { + name_mangling_version = + read_integral_parameter (p + 22, p - 2, name_mangling_version); + } + else for (j = 0; + !found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]); + j++) + { + if (!strcmp (p, lang_f_options[j].string)) + { + *lang_f_options[j].variable = lang_f_options[j].on_value; + /* A goto here would be cleaner, + but breaks the vax pcc. */ + found = 1; + } + if (p[0] == 'n' && p[1] == 'o' && p[2] == '-' + && ! strcmp (p+3, lang_f_options[j].string)) + { + *lang_f_options[j].variable = ! lang_f_options[j].on_value; + found = 1; + } + } + return found; + } + else if (p[0] == '-' && p[1] == 'W') + { + int setting = 1; + + /* The -W options control the warning behavior of the compiler. */ + p += 2; + + if (p[0] == 'n' && p[1] == 'o' && p[2] == '-') + setting = 0, p += 3; + + if (!strcmp (p, "implicit")) + warn_implicit = setting; + else if (!strcmp (p, "long-long")) + warn_long_long = setting; + else if (!strcmp (p, "return-type")) + warn_return_type = setting; + else if (!strcmp (p, "ctor-dtor-privacy")) + warn_ctor_dtor_privacy = setting; + else if (!strcmp (p, "write-strings")) + warn_write_strings = setting; + else if (!strcmp (p, "cast-qual")) + warn_cast_qual = setting; + else if (!strcmp (p, "char-subscripts")) + warn_char_subscripts = setting; + else if (!strcmp (p, "pointer-arith")) + warn_pointer_arith = setting; + else if (!strcmp (p, "missing-prototypes")) + warn_missing_prototypes = setting; + else if (!strcmp (p, "redundant-decls")) + warn_redundant_decls = setting; + else if (!strcmp (p, "missing-braces")) + warn_missing_braces = setting; + else if (!strcmp (p, "sign-compare")) + warn_sign_compare = setting; + else if (!strcmp (p, "format")) + warn_format = setting; + else if (!strcmp (p, "conversion")) + warn_conversion = setting; + else if (!strcmp (p, "parentheses")) + warn_parentheses = setting; + else if (!strcmp (p, "non-virtual-dtor")) + warn_nonvdtor = setting; + else if (!strcmp (p, "extern-inline")) + warn_extern_inline = setting; + else if (!strcmp (p, "reorder")) + warn_reorder = setting; + else if (!strcmp (p, "synth")) + warn_synth = setting; + else if (!strcmp (p, "pmf-conversions")) + warn_pmf2ptr = setting; + else if (!strcmp (p, "effc++")) + warn_ecpp = setting; + else if (!strcmp (p, "sign-promo")) + warn_sign_promo = setting; + else if (!strcmp (p, "old-style-cast")) + warn_old_style_cast = setting; + else if (!strcmp (p, "overloaded-virtual")) + warn_overloaded_virtual = setting; + else if (!strcmp (p, "multichar")) + warn_multichar = setting; + else if (!strcmp (p, "unknown-pragmas")) + /* Set to greater than 1, so that even unknown pragmas in + system headers will be warned about. */ + warn_unknown_pragmas = setting * 2; + else if (!strcmp (p, "non-template-friend")) + warn_nontemplate_friend = setting; + else if (!strcmp (p, "deprecated")) + warn_deprecated = setting; + else if (!strcmp (p, "comment")) + ; /* cpp handles this one. */ + else if (!strcmp (p, "comments")) + ; /* cpp handles this one. */ + else if (!strcmp (p, "trigraphs")) + ; /* cpp handles this one. */ + else if (!strcmp (p, "import")) + ; /* cpp handles this one. */ + else if (!strcmp (p, "all")) + { + warn_return_type = setting; + warn_unused = setting; + warn_implicit = setting; + warn_switch = setting; + warn_format = setting; + warn_parentheses = setting; + warn_missing_braces = setting; + warn_sign_compare = setting; + warn_multichar = setting; + /* We save the value of warn_uninitialized, since if they put + -Wuninitialized on the command line, we need to generate a + warning about not using it without also specifying -O. */ + if (warn_uninitialized != 1) + warn_uninitialized = (setting ? 2 : 0); + /* Only warn about unknown pragmas that are not in system + headers. */ + warn_unknown_pragmas = 1; + + /* C++-specific warnings. */ + warn_ctor_dtor_privacy = setting; + warn_nonvdtor = setting; + warn_reorder = setting; + warn_nontemplate_friend = setting; + } + else return strings_processed; + } + else if (!strcmp (p, "-ansi")) + flag_no_nonansi_builtin = 1, flag_ansi = 1, + flag_no_gnu_keywords = 1, flag_operator_names = 1; +#ifdef SPEW_DEBUG + /* Undocumented, only ever used when you're invoking cc1plus by hand, since + it's probably safe to assume no sane person would ever want to use this + under normal circumstances. */ + else if (!strcmp (p, "-spew-debug")) + spew_debug = 1; +#endif + else + return strings_processed; + + return 1; +} + +/* Incorporate `const' and `volatile' qualifiers for member functions. + FUNCTION is a TYPE_DECL or a FUNCTION_DECL. + QUALS is a list of qualifiers. */ + +tree +grok_method_quals (ctype, function, quals) + tree ctype, function, quals; +{ + tree fntype = TREE_TYPE (function); + tree raises = TYPE_RAISES_EXCEPTIONS (fntype); + int type_quals = TYPE_UNQUALIFIED; + int dup_quals = TYPE_UNQUALIFIED; + + do + { + int tq = cp_type_qual_from_rid (TREE_VALUE (quals)); + + if (type_quals & tq) + dup_quals |= tq; + else + type_quals |= tq; + quals = TREE_CHAIN (quals); + } + while (quals); + + if (dup_quals != TYPE_UNQUALIFIED) + cp_error ("duplicate type qualifiers in %s declaration", + TREE_CODE (function) == FUNCTION_DECL + ? "member function" : "type"); + + ctype = cp_build_qualified_type (ctype, type_quals); + fntype = build_cplus_method_type (ctype, TREE_TYPE (fntype), + (TREE_CODE (fntype) == METHOD_TYPE + ? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) + : TYPE_ARG_TYPES (fntype))); + if (raises) + fntype = build_exception_variant (fntype, raises); + + TREE_TYPE (function) = fntype; + return ctype; +} + +/* Warn when -fexternal-templates is used and #pragma + interface/implementation is not used all the times it should be, + inform the user. */ + +void +warn_if_unknown_interface (decl) + tree decl; +{ + static int already_warned = 0; + if (already_warned++) + return; + + if (flag_alt_external_templates) + { + struct tinst_level *til = tinst_for_decl (); + int sl = lineno; + char *sf = input_filename; + + if (til) + { + lineno = til->line; + input_filename = til->file; + } + cp_warning ("template `%#D' instantiated in file without #pragma interface", + decl); + lineno = sl; + input_filename = sf; + } + else + cp_warning_at ("template `%#D' defined in file without #pragma interface", + decl); +} + +/* A subroutine of the parser, to handle a component list. */ + +void +grok_x_components (specs) + tree specs; +{ + struct pending_inline **p; + tree t; + + specs = strip_attrs (specs); + + check_tag_decl (specs); + t = groktypename (build_decl_list (specs, NULL_TREE)); + + /* The only case where we need to do anything additional here is an + anonymous union field, e.g.: `struct S { union { int i; }; };'. */ + if (t == NULL_TREE || !ANON_UNION_TYPE_P (t)) + return; + + fixup_anonymous_union (t); + finish_member_declaration (build_lang_field_decl (FIELD_DECL, + NULL_TREE, + t)); + + /* Ignore any inline function definitions in the anonymous union + since an anonymous union may not have function members. */ + p = &pending_inlines; + for (; *p; *p = (*p)->next) + if (DECL_CONTEXT ((*p)->fndecl) != t) + break; +} + +/* Constructors for types with virtual baseclasses need an "in-charge" flag + saying whether this constructor is responsible for initialization of + virtual baseclasses or not. All destructors also need this "in-charge" + flag, which additionally determines whether or not the destructor should + free the memory for the object. + + This function adds the "in-charge" flag to member function FN if + appropriate. It is called from grokclassfn and tsubst. + FN must be either a constructor or destructor. + + For vtable thunks, types with polymorphic virtual bases need an + additional "vlist" argument which is an array of virtual tables. + In addition, if backwards-compatibility to v1 thunks is requested, + a wrapper constructor may be needed as well. */ + +void +maybe_retrofit_in_chrg (fn) + tree fn; +{ + tree basetype, arg_types, parms, parm, fntype; + tree wrapper; + + if (CLASSTYPE_IS_TEMPLATE (DECL_CLASS_CONTEXT (fn))) + /* Never retrofit arguments on template methods. */ + return; + + if (DECL_CONSTRUCTOR_P (fn) + && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn)) + && DECL_CONSTRUCTOR_FOR_VBASE (fn) == 0) + /* OK */; + else if (! DECL_CONSTRUCTOR_P (fn) + && TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE) + /* OK */; + else + return; + + if (DECL_CONSTRUCTOR_P (fn)) + { + if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn))) + DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_PVBASE; + else + DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_VBASE; + } + else if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn))) + DECL_CONSTRUCTOR_FOR_VBASE (fn) = DESTRUCTOR_FOR_PVBASE; + + /* Retrieve the arguments, because it is potentially modified twice. */ + arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); + basetype = TREE_TYPE (TREE_VALUE (arg_types)); + arg_types = TREE_CHAIN (arg_types); + + if (DECL_CONSTRUCTOR_FOR_PVBASE_P (fn) + || DECL_DESTRUCTOR_FOR_PVBASE_P (fn)) + { + /* Add the __vlist argument first. See __in_chrg below. */ + tree id = vlist_identifier; + if (DECL_DESTRUCTOR_FOR_PVBASE_P (fn)) + id = get_identifier (VLIST1_NAME); + parm = build_decl (PARM_DECL, id, vlist_type_node); + SET_DECL_ARTIFICIAL (parm); + DECL_ARG_TYPE (parm) = vlist_type_node; + parms = DECL_ARGUMENTS (fn); + /* Add it after 'this'. */ + TREE_CHAIN (parm) = TREE_CHAIN (parms); + TREE_CHAIN (parms) = parm; + + arg_types = hash_tree_chain (vlist_type_node, arg_types); + } + + /* First add it to DECL_ARGUMENTS... */ + parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); + /* Mark the artificial `__in_chrg' parameter as "artificial". */ + SET_DECL_ARTIFICIAL (parm); + DECL_ARG_TYPE (parm) = integer_type_node; + TREE_READONLY (parm) = 1; + parms = DECL_ARGUMENTS (fn); + TREE_CHAIN (parm) = TREE_CHAIN (parms); + TREE_CHAIN (parms) = parm; + + /* ...and then to TYPE_ARG_TYPES. */ + arg_types = hash_tree_chain (integer_type_node, arg_types); + fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), + arg_types); + if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) + fntype = build_exception_variant (fntype, + TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))); + TREE_TYPE (fn) = fntype; + + if (flag_vtable_thunks_compat + && DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) + make_vlist_ctor_wrapper (fn); +} + +/* Classes overload their constituent function names automatically. + When a function name is declared in a record structure, + its name is changed to it overloaded name. Since names for + constructors and destructors can conflict, we place a leading + '$' for destructors. + + CNAME is the name of the class we are grokking for. + + FUNCTION is a FUNCTION_DECL. It was created by `grokdeclarator'. + + FLAGS contains bits saying what's special about today's + arguments. 1 == DESTRUCTOR. 2 == OPERATOR. + + If FUNCTION is a destructor, then we must add the `auto-delete' field + as a second parameter. There is some hair associated with the fact + that we must "declare" this variable in the manner consistent with the + way the rest of the arguments were declared. + + QUALS are the qualifiers for the this pointer. */ + +void +grokclassfn (ctype, function, flags, quals) + tree ctype, function; + enum overload_flags flags; + tree quals; +{ + tree fn_name = DECL_NAME (function); + tree arg_types; + tree parm; + tree qualtype; + + if (fn_name == NULL_TREE) + { + error ("name missing for member function"); + fn_name = get_identifier (""); + DECL_NAME (function) = fn_name; + } + + if (quals) + qualtype = grok_method_quals (ctype, function, quals); + else + qualtype = ctype; + + arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); + if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) + { + /* Must add the class instance variable up front. */ + /* Right now we just make this a pointer. But later + we may wish to make it special. */ + tree type = TREE_VALUE (arg_types); + int constp = 1; + + if ((flag_this_is_variable > 0) + && (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))) + constp = 0; + + parm = build_decl (PARM_DECL, this_identifier, type); + /* Mark the artificial `this' parameter as "artificial". */ + SET_DECL_ARTIFICIAL (parm); + DECL_ARG_TYPE (parm) = type; + /* We can make this a register, so long as we don't + accidentally complain if someone tries to take its address. */ + DECL_REGISTER (parm) = 1; + if (constp) + TREE_READONLY (parm) = 1; + TREE_CHAIN (parm) = last_function_parms; + last_function_parms = parm; + } + + DECL_ARGUMENTS (function) = last_function_parms; + /* First approximations. */ + DECL_CONTEXT (function) = ctype; + DECL_CLASS_CONTEXT (function) = ctype; + + if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function)) + { + maybe_retrofit_in_chrg (function); + arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); + } + + if (flags == DTOR_FLAG) + { + DECL_ASSEMBLER_NAME (function) = + build_destructor_name (ctype, DECL_DESTRUCTOR_FOR_PVBASE_P (function)); + TYPE_HAS_DESTRUCTOR (ctype) = 1; + } + else + set_mangled_name_for_decl (function); +} + +/* Work on the expr used by alignof (this is only called by the parser). */ + +tree +grok_alignof (expr) + tree expr; +{ + tree best, t; + int bestalign; + + if (processing_template_decl) + return build_min (ALIGNOF_EXPR, sizetype, expr); + + if (TREE_CODE (expr) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1))) + error ("`__alignof__' applied to a bit-field"); + + if (TREE_CODE (expr) == INDIRECT_REF) + { + best = t = TREE_OPERAND (expr, 0); + bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); + + while (TREE_CODE (t) == NOP_EXPR + && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE) + { + int thisalign; + t = TREE_OPERAND (t, 0); + thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); + if (thisalign > bestalign) + best = t, bestalign = thisalign; + } + return c_alignof (TREE_TYPE (TREE_TYPE (best))); + } + else + { + /* ANSI says arrays and fns are converted inside comma. + But we can't convert them in build_compound_expr + because that would break commas in lvalues. + So do the conversion here if operand was a comma. */ + if (TREE_CODE (expr) == COMPOUND_EXPR + && (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE + || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)) + expr = default_conversion (expr); + return c_alignof (TREE_TYPE (expr)); + } +} + +/* Create an ARRAY_REF, checking for the user doing things backwards + along the way. */ + +tree +grok_array_decl (array_expr, index_exp) + tree array_expr, index_exp; +{ + tree type = TREE_TYPE (array_expr); + tree p1, p2, i1, i2; + + if (type == error_mark_node || index_exp == error_mark_node) + return error_mark_node; + if (processing_template_decl) + return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE, + array_expr, index_exp); + + if (type == NULL_TREE) + { + /* Something has gone very wrong. Assume we are mistakenly reducing + an expression instead of a declaration. */ + error ("parser may be lost: is there a '{' missing somewhere?"); + return NULL_TREE; + } + + if (TREE_CODE (type) == OFFSET_TYPE + || TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); + + /* If they have an `operator[]', use that. */ + if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp))) + return build_opfncall (ARRAY_REF, LOOKUP_NORMAL, + array_expr, index_exp, NULL_TREE); + + /* Otherwise, create an ARRAY_REF for a pointer or array type. It + is a little-known fact that, if `a' is an array and `i' is an + int, you can write `i[a]', which means the same thing as `a[i]'. */ + + if (TREE_CODE (type) == ARRAY_TYPE) + p1 = array_expr; + else + p1 = build_expr_type_conversion (WANT_POINTER, array_expr, 0); + + if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE) + p2 = index_exp; + else + p2 = build_expr_type_conversion (WANT_POINTER, index_exp, 0); + + i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, 0); + i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, 0); + + if ((p1 && i2) && (i1 && p2)) + error ("ambiguous conversion for array subscript"); + + if (p1 && i2) + array_expr = p1, index_exp = i2; + else if (i1 && p2) + array_expr = p2, index_exp = i1; + else + { + cp_error ("invalid types `%T[%T]' for array subscript", + type, TREE_TYPE (index_exp)); + return error_mark_node; + } + + if (array_expr == error_mark_node || index_exp == error_mark_node) + error ("ambiguous conversion for array subscript"); + + return build_array_ref (array_expr, index_exp); +} + +/* Given the cast expression EXP, checking out its validity. Either return + an error_mark_node if there was an unavoidable error, return a cast to + void for trying to delete a pointer w/ the value 0, or return the + call to delete. If DOING_VEC is 1, we handle things differently + for doing an array delete. If DOING_VEC is 2, they gave us the + array size as an argument to delete. + Implements ARM $5.3.4. This is called from the parser. */ + +tree +delete_sanity (exp, size, doing_vec, use_global_delete) + tree exp, size; + int doing_vec, use_global_delete; +{ + tree t, type; + /* For a regular vector delete (aka, no size argument) we will pass + this down as a NULL_TREE into build_vec_delete. */ + tree maxindex = NULL_TREE; + + if (exp == error_mark_node) + return exp; + + if (processing_template_decl) + { + t = build_min (DELETE_EXPR, void_type_node, exp, size); + DELETE_EXPR_USE_GLOBAL (t) = use_global_delete; + DELETE_EXPR_USE_VEC (t) = doing_vec; + return t; + } + + if (TREE_CODE (exp) == OFFSET_REF) + exp = resolve_offset_ref (exp); + exp = convert_from_reference (exp); + t = stabilize_reference (exp); + t = build_expr_type_conversion (WANT_POINTER, t, 1); + + if (t == NULL_TREE || t == error_mark_node) + { + cp_error ("type `%#T' argument given to `delete', expected pointer", + TREE_TYPE (exp)); + return error_mark_node; + } + + if (doing_vec == 2) + { + maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node); + pedwarn ("anachronistic use of array size in vector delete"); + } + + type = TREE_TYPE (t); + + /* As of Valley Forge, you can delete a pointer to const. */ + + /* You can't delete functions. */ + if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + { + error ("cannot delete a function"); + return error_mark_node; + } + + /* Deleting ptr to void is undefined behaviour [expr.delete/3]. */ + if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE) + cp_warning ("`%T' is not a pointer-to-object type", type); + + /* An array can't have been allocated by new, so complain. */ + if (TREE_CODE (t) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL + && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == ARRAY_TYPE) + cp_warning ("deleting array `%#D'", TREE_OPERAND (t, 0)); + + /* Deleting a pointer with the value zero is valid and has no effect. */ + if (integer_zerop (t)) + return build1 (NOP_EXPR, void_type_node, t); + + if (doing_vec) + return build_vec_delete (t, maxindex, integer_one_node, + integer_zero_node, use_global_delete); + else + { + if (IS_AGGR_TYPE (TREE_TYPE (type)) + && TYPE_GETS_REG_DELETE (TREE_TYPE (type))) + { + /* Only do access checking here; we'll be calling op delete + from the destructor. */ + tree tmp = build_op_delete_call (DELETE_EXPR, t, size_zero_node, + LOOKUP_NORMAL, NULL_TREE); + if (tmp == error_mark_node) + return error_mark_node; + } + + return build_delete (type, t, integer_three_node, + LOOKUP_NORMAL, use_global_delete); + } +} + +/* Report an error if the indicated template declaration is not the + sort of thing that should be a member template. */ + +void +check_member_template (tmpl) + tree tmpl; +{ + tree decl; + + my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); + decl = DECL_TEMPLATE_RESULT (tmpl); + + if (TREE_CODE (decl) == FUNCTION_DECL + || (TREE_CODE (decl) == TYPE_DECL + && IS_AGGR_TYPE (TREE_TYPE (decl)))) + { + if (current_function_decl) + /* 14.5.2.2 [temp.mem] + + A local class shall not have member templates. */ + cp_error ("declaration of member template `%#D' in local class", + decl); + + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl)) + { + /* 14.5.2.3 [temp.mem] + + A member function template shall not be virtual. */ + cp_error + ("invalid use of `virtual' in template declaration of `%#D'", + decl); + DECL_VIRTUAL_P (decl) = 0; + } + + /* The debug-information generating code doesn't know what to do + with member templates. */ + DECL_IGNORED_P (tmpl) = 1; + } + else + cp_error ("template declaration of `%#D'", decl); +} + +/* Return true iff TYPE is a valid Java parameter or return type. */ + +static int +acceptable_java_type (type) + tree type; +{ + if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type)) + return 1; + if (TREE_CODE (type) == POINTER_TYPE) + { + type = TREE_TYPE (type); + if (TREE_CODE (type) == RECORD_TYPE) + { + tree args; int i; + if (! TYPE_FOR_JAVA (type)) + return 0; + if (! CLASSTYPE_TEMPLATE_INFO (type)) + return 1; + args = CLASSTYPE_TI_ARGS (type); + i = TREE_VEC_LENGTH (args); + while (--i >= 0) + { + type = TREE_VEC_ELT (args, i); + if (TREE_CODE (type) == POINTER_TYPE) + type = TREE_TYPE (type); + if (! TYPE_FOR_JAVA (type)) + return 0; + } + return 1; + } + } + return 0; +} + +/* For a METHOD in a Java class CTYPE, return 1 if + the parameter and return types are valid Java types. + Otherwise, print appropriate error messages, and return 0. */ + +int +check_java_method (method) + tree method; +{ + int jerr = 0; + tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (method)); + tree ret_type = TREE_TYPE (TREE_TYPE (method)); + if (! acceptable_java_type (ret_type)) + { + cp_error ("Java method '%D' has non-Java return type `%T'", + method, ret_type); + jerr++; + } + for (; arg_types != NULL_TREE; arg_types = TREE_CHAIN (arg_types)) + { + tree type = TREE_VALUE (arg_types); + if (! acceptable_java_type (type)) + { + cp_error ("Java method '%D' has non-Java parameter type `%T'", + method, type); + jerr++; + } + } + return jerr ? 0 : 1; +} + +/* Sanity check: report error if this function FUNCTION is not + really a member of the class (CTYPE) it is supposed to belong to. + CNAME is the same here as it is for grokclassfn above. */ + +tree +check_classfn (ctype, function) + tree ctype, function; +{ + tree fn_name = DECL_NAME (function); + tree fndecl, fndecls; + tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype)); + tree *methods = 0; + tree *end = 0; + + if (DECL_USE_TEMPLATE (function) + && is_member_template (DECL_TI_TEMPLATE (function))) + /* Since this is a specialization of a member template, + we're not going to find the declaration in the class. + For example, in: + + struct S { template void f(T); }; + template <> void S::f(int); + + we're not going to find `S::f(int)', but there's no + reason we should, either. We let our callers know we didn't + find the method, but we don't complain. */ + return NULL_TREE; + + if (method_vec != 0) + { + methods = &TREE_VEC_ELT (method_vec, 0); + end = TREE_VEC_END (method_vec); + + /* First suss out ctors and dtors. */ + if (*methods && fn_name == DECL_NAME (OVL_CURRENT (*methods)) + && DECL_CONSTRUCTOR_P (function)) + goto got_it; + if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods)) + && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))) + goto got_it; + + while (++methods != end && *methods) + { + fndecl = *methods; + if (fn_name == DECL_NAME (OVL_CURRENT (*methods))) + { + got_it: + for (fndecls = *methods; fndecls != NULL_TREE; + fndecls = OVL_NEXT (fndecls)) + { + fndecl = OVL_CURRENT (fndecls); + /* 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. + (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; + + /* We cannot simply call decls_match because this + doesn't work for static member functions that are + pretending to be methods, and because the name + may have been changed by asm("new_name"). */ + if (DECL_NAME (function) == DECL_NAME (fndecl)) + { + tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function)); + tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + + /* Get rid of the this parameter on functions that become + static. */ + if (DECL_STATIC_FUNCTION_P (fndecl) + && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) + p1 = TREE_CHAIN (p1); + + if (same_type_p (TREE_TYPE (TREE_TYPE (function)), + TREE_TYPE (TREE_TYPE (fndecl))) + && compparms (p1, p2) + && (DECL_TEMPLATE_SPECIALIZATION (function) + == DECL_TEMPLATE_SPECIALIZATION (fndecl)) + && (!DECL_TEMPLATE_SPECIALIZATION (function) + || (DECL_TI_TEMPLATE (function) + == DECL_TI_TEMPLATE (fndecl)))) + return fndecl; + } + } + break; /* loser */ + } + } + } + + if (methods != end && *methods) + { + tree fndecl = *methods; + cp_error ("prototype for `%#D' does not match any in class `%T'", + function, ctype); + cp_error_at ("candidate%s: %+#D", OVL_NEXT (fndecl) ? "s are" : " is", + OVL_CURRENT (fndecl)); + while (fndecl = OVL_NEXT (fndecl), fndecl) + cp_error_at (" %#D", OVL_CURRENT(fndecl)); + } + else + { + methods = 0; + if (TYPE_SIZE (ctype) == 0) + incomplete_type_error (function, ctype); + else + cp_error ("no `%#D' member function declared in class `%T'", + function, ctype); + } + + /* If we did not find the method in the class, add it to avoid + 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; +} + +/* We have just processed the DECL, which is a static data member. + Its initializer, if present, is INIT. The ASMSPEC_TREE, if + present, is the assembly-language name for the data member. + NEED_POP and FLAGS are as for cp_finish_decl. */ + +void +finish_static_data_member_decl (decl, init, asmspec_tree, need_pop, flags) + tree decl; + tree init; + tree asmspec_tree; + int need_pop; + int flags; +{ + char* asmspec = 0; + + if (asmspec_tree) + asmspec = TREE_STRING_POINTER (asmspec_tree); + + my_friendly_assert (TREE_PUBLIC (decl), 0); + + /* We cannot call pushdecl here, because that would fill in the + decl of our TREE_CHAIN. Instead, we modify cp_finish_decl to do + the right thing, namely, to put this decl out straight away. */ + /* current_class_type can be NULL_TREE in case of error. */ + if (!asmspec && current_class_type) + { + DECL_INITIAL (decl) = error_mark_node; + DECL_ASSEMBLER_NAME (decl) + = build_static_name (current_class_type, DECL_NAME (decl)); + } + if (! processing_template_decl) + { + if (!pending_statics) + VARRAY_TREE_INIT (pending_statics, 32, "pending_statics"); + + if (pending_statics_used == pending_statics->num_elements) + VARRAY_GROW (pending_statics, + 2 * pending_statics->num_elements); + VARRAY_TREE (pending_statics, pending_statics_used) = decl; + ++pending_statics_used; + } + + /* Static consts need not be initialized in the class definition. */ + if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) + { + static int explanation = 0; + + error ("initializer invalid for static member with constructor"); + if (explanation++ == 0) + error ("(you really want to initialize it separately)"); + init = 0; + } + /* Force the compiler to know when an uninitialized static const + member is being used. */ + if (CP_TYPE_CONST_P (TREE_TYPE (decl)) && init == 0) + TREE_USED (decl) = 1; + DECL_INITIAL (decl) = init; + DECL_IN_AGGR_P (decl) = 1; + DECL_CONTEXT (decl) = current_class_type; + DECL_CLASS_CONTEXT (decl) = current_class_type; + + cp_finish_decl (decl, init, asmspec_tree, need_pop, flags); +} + +/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted) + of a structure component, returning a FIELD_DECL node. + QUALS is a list of type qualifiers for this decl (such as for declaring + const member functions). + + This is done during the parsing of the struct declaration. + The FIELD_DECL nodes are chained together and the lot of them + are ultimately passed to `build_struct' to make the RECORD_TYPE node. + + C++: + + If class A defines that certain functions in class B are friends, then + the way I have set things up, it is B who is interested in permission + granted by A. However, it is in A's context that these declarations + are parsed. By returning a void_type_node, class A does not attempt + to incorporate the declarations of the friends within its structure. + + DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING + CHANGES TO CODE IN `start_method'. */ + +tree +grokfield (declarator, declspecs, init, asmspec_tree, attrlist) + tree declarator, declspecs, init, asmspec_tree, attrlist; +{ + register tree value; + char *asmspec = 0; + int flags = LOOKUP_ONLYCONVERTING; + + /* Convert () initializers to = initializers. */ + if (init == NULL_TREE && declarator != NULL_TREE + && TREE_CODE (declarator) == CALL_EXPR + && TREE_OPERAND (declarator, 0) + && (TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE + || TREE_CODE (TREE_OPERAND (declarator, 0)) == SCOPE_REF) + && parmlist_is_exprlist (TREE_OPERAND (declarator, 1))) + { + init = TREE_OPERAND (declarator, 1); + declarator = TREE_OPERAND (declarator, 0); + flags = 0; + } + + if (declspecs == NULL_TREE + && TREE_CODE (declarator) == SCOPE_REF + && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE) + { + /* Access declaration */ + if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0)))) + ; + else if (TREE_COMPLEXITY (declarator) == current_class_depth) + pop_nested_class (); + return do_class_using_decl (declarator); + } + + if (init + && TREE_CODE (init) == TREE_LIST + && TREE_VALUE (init) == error_mark_node + && TREE_CHAIN (init) == NULL_TREE) + init = NULL_TREE; + + value = grokdeclarator (declarator, declspecs, FIELD, init != 0, attrlist); + if (! value || value == error_mark_node) + /* friend or constructor went bad. */ + return value; + + /* Pass friendly classes back. */ + if (TREE_CODE (value) == VOID_TYPE) + return void_type_node; + + if (DECL_NAME (value) != NULL_TREE + && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_' + && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr")) + cp_error ("member `%D' conflicts with virtual function table field name", + value); + + /* Stash away type declarations. */ + if (TREE_CODE (value) == TYPE_DECL) + { + DECL_NONLOCAL (value) = 1; + DECL_CONTEXT (value) = current_class_type; + DECL_CLASS_CONTEXT (value) = current_class_type; + + /* Now that we've updated the context, we need to remangle the + name for this TYPE_DECL. */ + DECL_ASSEMBLER_NAME (value) = DECL_NAME (value); + if (!uses_template_parms (value)) + DECL_ASSEMBLER_NAME (value) = + get_identifier (build_overload_name (TREE_TYPE (value), 1, 1)); + + return value; + } + + if (IS_SIGNATURE (current_class_type) + && TREE_CODE (value) != FUNCTION_DECL) + { + error ("field declaration not allowed in signature"); + return void_type_node; + } + + if (DECL_IN_AGGR_P (value)) + { + cp_error ("`%D' is already defined in `%T'", value, + DECL_CONTEXT (value)); + return void_type_node; + } + + if (asmspec_tree) + asmspec = TREE_STRING_POINTER (asmspec_tree); + + if (init) + { + if (IS_SIGNATURE (current_class_type) + && TREE_CODE (value) == FUNCTION_DECL) + { + error ("function declarations cannot have initializers in signature"); + init = NULL_TREE; + } + else if (TREE_CODE (value) == FUNCTION_DECL) + { + grok_function_init (value, init); + init = NULL_TREE; + } + else if (pedantic && TREE_CODE (value) != VAR_DECL) + /* Already complained in grokdeclarator. */ + init = NULL_TREE; + else + { + /* We allow initializers to become parameters to base + initializers. */ + if (TREE_CODE (init) == TREE_LIST) + { + if (TREE_CHAIN (init) == NULL_TREE) + init = TREE_VALUE (init); + else + init = digest_init (TREE_TYPE (value), init, (tree *)0); + } + + if (TREE_CODE (init) == CONST_DECL) + init = DECL_INITIAL (init); + else if (TREE_READONLY_DECL_P (init)) + init = decl_constant_value (init); + else if (TREE_CODE (init) == CONSTRUCTOR) + init = digest_init (TREE_TYPE (value), init, (tree *)0); + my_friendly_assert (TREE_PERMANENT (init), 192); + if (init == error_mark_node) + /* We must make this look different than `error_mark_node' + because `decl_const_value' would mis-interpret it + as only meaning that this VAR_DECL is defined. */ + init = build1 (NOP_EXPR, TREE_TYPE (value), init); + else if (processing_template_decl) + ; + else if (! TREE_CONSTANT (init)) + { + /* We can allow references to things that are effectively + static, since references are initialized with the address. */ + if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE + || (TREE_STATIC (init) == 0 + && (TREE_CODE_CLASS (TREE_CODE (init)) != 'd' + || DECL_EXTERNAL (init) == 0))) + { + error ("field initializer is not constant"); + init = error_mark_node; + } + } + } + } + + /* The corresponding pop_obstacks is in cp_finish_decl. */ + push_obstacks_nochange (); + + if (processing_template_decl && ! current_function_decl + && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL)) + value = push_template_decl (value); + + if (attrlist) + cplus_decl_attributes (value, TREE_PURPOSE (attrlist), + TREE_VALUE (attrlist)); + + if (TREE_CODE (value) == VAR_DECL) + { + finish_static_data_member_decl (value, init, asmspec_tree, + /*need_pop=*/1, flags); + return value; + } + if (TREE_CODE (value) == FIELD_DECL) + { + if (asmspec) + { + /* This must override the asm specifier which was placed + by grokclassfn. Lay this out fresh. */ + DECL_RTL (value) = NULL_RTX; + DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec); + } + if (DECL_INITIAL (value) == error_mark_node) + init = error_mark_node; + cp_finish_decl (value, init, asmspec_tree, 1, flags); + DECL_INITIAL (value) = init; + DECL_IN_AGGR_P (value) = 1; + return value; + } + if (TREE_CODE (value) == FUNCTION_DECL) + { + if (asmspec) + { + /* This must override the asm specifier which was placed + by grokclassfn. Lay this out fresh. */ + DECL_RTL (value) = NULL_RTX; + DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec); + } + cp_finish_decl (value, init, asmspec_tree, 1, flags); + + /* Pass friends back this way. */ + if (DECL_FRIEND_P (value)) + return void_type_node; + +#if 0 /* Just because a fn is declared doesn't mean we'll try to define it. */ + if (current_function_decl && ! IS_SIGNATURE (current_class_type)) + cp_error ("method `%#D' of local class must be defined in class body", + value); +#endif + + DECL_IN_AGGR_P (value) = 1; + return value; + } + my_friendly_abort (21); + /* NOTREACHED */ + return NULL_TREE; +} + +/* Like `grokfield', but for bitfields. + WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */ + +tree +grokbitfield (declarator, declspecs, width) + tree declarator, declspecs, width; +{ + register tree value = grokdeclarator (declarator, declspecs, BITFIELD, + 0, NULL_TREE); + + if (! value) return NULL_TREE; /* friends went bad. */ + + /* Pass friendly classes back. */ + if (TREE_CODE (value) == VOID_TYPE) + return void_type_node; + + if (TREE_CODE (value) == TYPE_DECL) + { + cp_error ("cannot declare `%D' to be a bitfield type", value); + return NULL_TREE; + } + + /* Usually, finish_struct_1 catches bitifields with invalid types. + But, in the case of bitfields with function type, we confuse + ourselves into thinking they are member functions, so we must + check here. */ + if (TREE_CODE (value) == FUNCTION_DECL) + { + cp_error ("cannot declare bitfield `%D' with funcion type", + DECL_NAME (value)); + return NULL_TREE; + } + + if (IS_SIGNATURE (current_class_type)) + { + error ("field declaration not allowed in signature"); + return void_type_node; + } + + if (DECL_IN_AGGR_P (value)) + { + cp_error ("`%D' is already defined in the class %T", value, + DECL_CONTEXT (value)); + return void_type_node; + } + + GNU_xref_member (current_class_name, value); + + if (TREE_STATIC (value)) + { + cp_error ("static member `%D' cannot be a bitfield", value); + return NULL_TREE; + } + cp_finish_decl (value, NULL_TREE, NULL_TREE, 0, 0); + + if (width != error_mark_node) + { + constant_expression_warning (width); + DECL_INITIAL (value) = width; + SET_DECL_C_BIT_FIELD (value); + } + + DECL_IN_AGGR_P (value) = 1; + return value; +} + +tree +grokoptypename (declspecs, declarator) + tree declspecs, declarator; +{ + tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE); + return build_typename_overload (t); +} + +/* When a function is declared with an initializer, + do the right thing. Currently, there are two possibilities: + + class B + { + public: + // initialization possibility #1. + virtual void f () = 0; + int g (); + }; + + class D1 : B + { + public: + int d1; + // error, no f (); + }; + + class D2 : B + { + public: + int d2; + void f (); + }; + + class D3 : B + { + public: + int d3; + // initialization possibility #2 + void f () = B::f; + }; + +*/ + +int +copy_assignment_arg_p (parmtype, virtualp) + tree parmtype; + int virtualp ATTRIBUTE_UNUSED; +{ + if (current_class_type == NULL_TREE) + return 0; + + if (TREE_CODE (parmtype) == REFERENCE_TYPE) + parmtype = TREE_TYPE (parmtype); + + if ((TYPE_MAIN_VARIANT (parmtype) == current_class_type) +#if 0 + /* Non-standard hack to support old Booch components. */ + || (! virtualp && DERIVED_FROM_P (parmtype, current_class_type)) +#endif + ) + return 1; + + return 0; +} + +static void +grok_function_init (decl, init) + tree decl; + tree init; +{ + /* An initializer for a function tells how this function should + be inherited. */ + tree type = TREE_TYPE (decl); + + if (TREE_CODE (type) == FUNCTION_TYPE) + cp_error ("initializer specified for non-member function `%D'", decl); +#if 0 + /* We'll check for this in finish_struct_1. */ + else if (DECL_VINDEX (decl) == NULL_TREE) + cp_error ("initializer specified for non-virtual method `%D'", decl); +#endif + else if (integer_zerop (init)) + { +#if 0 + /* Mark this function as being "defined". */ + DECL_INITIAL (decl) = error_mark_node; + /* pure virtual destructors must be defined. */ + /* pure virtual needs to be defined (as abort) only when put in + vtbl. For wellformed call, it should be itself. pr4737 */ + if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))) + { + extern tree abort_fndecl; + /* Give this node rtl from `abort'. */ + DECL_RTL (decl) = DECL_RTL (abort_fndecl); + } +#endif + DECL_ABSTRACT_VIRTUAL_P (decl) = 1; + if (DECL_NAME (decl) == ansi_opname [(int) MODIFY_EXPR]) + { + tree parmtype + = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))); + + if (copy_assignment_arg_p (parmtype, 1)) + TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1; + } + } + else + cp_error ("invalid initializer for virtual method `%D'", decl); +} + +void +cplus_decl_attributes (decl, attributes, prefix_attributes) + tree decl, attributes, prefix_attributes; +{ + if (decl == NULL_TREE || decl == void_type_node) + return; + + if (TREE_CODE (decl) == TEMPLATE_DECL) + decl = DECL_TEMPLATE_RESULT (decl); + + decl_attributes (decl, attributes, prefix_attributes); + + if (TREE_CODE (decl) == TYPE_DECL) + SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (decl), TREE_TYPE (decl)); +} + +/* CONSTRUCTOR_NAME: + Return the name for the constructor (or destructor) for the + specified class. Argument can be RECORD_TYPE, TYPE_DECL, or + IDENTIFIER_NODE. When given a template, this routine doesn't + lose the specialization. */ + +tree +constructor_name_full (thing) + tree thing; +{ + if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM + || TREE_CODE (thing) == TEMPLATE_TEMPLATE_PARM + || TREE_CODE (thing) == TYPENAME_TYPE) + thing = TYPE_NAME (thing); + else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing))) + { + if (TYPE_WAS_ANONYMOUS (thing) && TYPE_HAS_CONSTRUCTOR (thing)) + thing = DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (thing), 0))); + else + thing = TYPE_NAME (thing); + } + if (TREE_CODE (thing) == TYPE_DECL + || (TREE_CODE (thing) == TEMPLATE_DECL + && TREE_CODE (DECL_TEMPLATE_RESULT (thing)) == TYPE_DECL)) + thing = DECL_NAME (thing); + my_friendly_assert (TREE_CODE (thing) == IDENTIFIER_NODE, 197); + return thing; +} + +/* CONSTRUCTOR_NAME: + Return the name for the constructor (or destructor) for the + specified class. Argument can be RECORD_TYPE, TYPE_DECL, or + IDENTIFIER_NODE. When given a template, return the plain + unspecialized name. */ + +tree +constructor_name (thing) + tree thing; +{ + tree t; + thing = constructor_name_full (thing); + t = IDENTIFIER_TEMPLATE (thing); + if (!t) + return thing; + return t; +} + +/* Cache the value of this class's main virtual function table pointer + in a register variable. This will save one indirection if a + more than one virtual function call is made this function. */ + +void +setup_vtbl_ptr () +{ + extern tree base_init_expr; + + if (base_init_expr == 0 + && DECL_CONSTRUCTOR_P (current_function_decl)) + { + if (processing_template_decl) + add_tree (build_min_nt + (CTOR_INITIALIZER, + current_member_init_list, current_base_init_list)); + else + emit_base_init (current_class_type, 0); + } +} + +/* Record the existence of an addressable inline function. */ + +void +mark_inline_for_output (decl) + tree decl; +{ + decl = DECL_MAIN_VARIANT (decl); + if (DECL_SAVED_INLINE (decl)) + return; + my_friendly_assert (TREE_PERMANENT (decl), 363); + DECL_SAVED_INLINE (decl) = 1; + if (!saved_inlines) + VARRAY_TREE_INIT (saved_inlines, 32, "saved_inlines"); + + if (saved_inlines_used == saved_inlines->num_elements) + VARRAY_GROW (saved_inlines, + 2 * saved_inlines->num_elements); + VARRAY_TREE (saved_inlines, saved_inlines_used) = decl; + ++saved_inlines_used; +} + +void +clear_temp_name () +{ + temp_name_counter = 0; +} + +/* Hand off a unique name which can be used for variable we don't really + want to know about anyway, for example, the anonymous variables which + are needed to make references work. Declare this thing so we can use it. + The variable created will be of type TYPE. + + STATICP is nonzero if this variable should be static. */ + +tree +get_temp_name (type, staticp) + tree type; + int staticp; +{ + char buf[sizeof (AUTO_TEMP_FORMAT) + 20]; + tree decl; + int toplev = toplevel_bindings_p (); + + push_obstacks_nochange (); + if (toplev || staticp) + { + end_temporary_allocation (); + sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++); + decl = pushdecl_top_level (build_decl (VAR_DECL, get_identifier (buf), type)); + } + else + { + sprintf (buf, AUTO_TEMP_FORMAT, temp_name_counter++); + decl = pushdecl (build_decl (VAR_DECL, get_identifier (buf), type)); + } + TREE_USED (decl) = 1; + TREE_STATIC (decl) = staticp; + DECL_ARTIFICIAL (decl) = 1; + + /* If this is a local variable, then lay out its rtl now. + Otherwise, callers of this function are responsible for dealing + with this variable's rtl. */ + if (! toplev) + { + expand_decl (decl); + expand_decl_init (decl); + } + pop_obstacks (); + + return decl; +} + +/* Get a variable which we can use for multiple assignments. + It is not entered into current_binding_level, because + that breaks things when it comes time to do final cleanups + (which take place "outside" the binding contour of the function). */ + +tree +get_temp_regvar (type, init) + tree type, init; +{ + tree decl; + + decl = build_decl (VAR_DECL, NULL_TREE, type); + TREE_USED (decl) = 1; + DECL_REGISTER (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + + DECL_RTL (decl) = assign_temp (type, 2, 0, 1); + /* We can expand these without fear, since they cannot need + constructors or destructors. */ + expand_expr (build_modify_expr (decl, INIT_EXPR, init), + NULL_RTX, VOIDmode, 0); + + return decl; +} + +/* Hunts through the global anonymous union ANON_DECL, building + appropriate VAR_DECLs. Stores cleanups on the list of ELEMS, and + returns a VAR_DECL whose size is the same as the size of the + ANON_DECL, if one is available. */ + +static tree +build_anon_union_vars (anon_decl, elems, static_p, external_p) + tree anon_decl; + tree* elems; + int static_p; + int external_p; +{ + tree type = TREE_TYPE (anon_decl); + tree main_decl = NULL_TREE; + tree field; + + for (field = TYPE_FIELDS (type); + field != NULL_TREE; + field = TREE_CHAIN (field)) + { + tree decl; + + if (DECL_ARTIFICIAL (field)) + continue; + if (TREE_CODE (field) != FIELD_DECL) + { + cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members", + field); + continue; + } + + if (TREE_PRIVATE (field)) + cp_pedwarn_at ("private member `%#D' in anonymous union", field); + else if (TREE_PROTECTED (field)) + cp_pedwarn_at ("protected member `%#D' in anonymous union", field); + + if (DECL_NAME (field) == NULL_TREE + && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + { + decl = build_anon_union_vars (field, elems, static_p, external_p); + if (!decl) + continue; + } + else if (DECL_NAME (field) == NULL_TREE) + continue; + else + { + decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field)); + /* tell `pushdecl' that this is not tentative. */ + DECL_INITIAL (decl) = error_mark_node; + TREE_PUBLIC (decl) = 0; + TREE_STATIC (decl) = static_p; + DECL_EXTERNAL (decl) = external_p; + decl = pushdecl (decl); + DECL_INITIAL (decl) = NULL_TREE; + } + + /* Only write out one anon union element--choose the one that + can hold them all. */ + if (main_decl == NULL_TREE + && simple_cst_equal (DECL_SIZE (decl), + DECL_SIZE (anon_decl)) == 1) + main_decl = decl; + else + /* ??? This causes there to be no debug info written out + about this decl. */ + TREE_ASM_WRITTEN (decl) = 1; + + if (DECL_NAME (field) == NULL_TREE + && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + /* The remainder of the processing was already done in the + recursive call. */ + continue; + + /* If there's a cleanup to do, it belongs in the + TREE_PURPOSE of the following TREE_LIST. */ + *elems = scratch_tree_cons (NULL_TREE, decl, *elems); + TREE_TYPE (*elems) = type; + } + + return main_decl; +} + +/* Finish off the processing of a UNION_TYPE structure. + If there are static members, then all members are + static, and must be laid out together. If the + union is an anonymous union, we arrange for that + as well. PUBLIC_P is nonzero if this union is + not declared static. */ + +void +finish_anon_union (anon_union_decl) + tree anon_union_decl; +{ + tree type = TREE_TYPE (anon_union_decl); + tree elems = NULL_TREE; + tree main_decl; + int public_p = TREE_PUBLIC (anon_union_decl); + int static_p = TREE_STATIC (anon_union_decl); + int external_p = DECL_EXTERNAL (anon_union_decl); + + if (TYPE_FIELDS (type) == NULL_TREE) + return; + + if (public_p) + { + error ("global anonymous unions must be declared static"); + return; + } + + main_decl = build_anon_union_vars (anon_union_decl, &elems, + static_p, external_p); + + if (main_decl == NULL_TREE) + { + warning ("anonymous union with no members"); + return; + } + + if (static_p) + { + make_decl_rtl (main_decl, 0, toplevel_bindings_p ()); + DECL_RTL (anon_union_decl) = DECL_RTL (main_decl); + } + + /* The following call assumes that there are never any cleanups + for anonymous unions--a reasonable assumption. */ + expand_anon_union_decl (anon_union_decl, NULL_TREE, elems); +} + +/* Finish processing a builtin type TYPE. It's name is NAME, + its fields are in the array FIELDS. LEN is the number of elements + in FIELDS minus one, or put another way, it is the maximum subscript + used in FIELDS. + + It is given the same alignment as ALIGN_TYPE. */ + +void +finish_builtin_type (type, name, fields, len, align_type) + tree type; + const char *name; + tree fields[]; + int len; + tree align_type; +{ + register int i; + + TYPE_FIELDS (type) = fields[0]; + for (i = 0; i < len; i++) + { + layout_type (TREE_TYPE (fields[i])); + DECL_FIELD_CONTEXT (fields[i]) = type; + TREE_CHAIN (fields[i]) = fields[i+1]; + } + DECL_FIELD_CONTEXT (fields[i]) = type; + DECL_CLASS_CONTEXT (fields[i]) = type; + TYPE_ALIGN (type) = TYPE_ALIGN (align_type); + layout_type (type); +#if 0 /* not yet, should get fixed properly later */ + TYPE_NAME (type) = make_type_decl (get_identifier (name), type); +#else + TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type); +#endif + TYPE_STUB_DECL (type) = TYPE_NAME (type); + layout_decl (TYPE_NAME (type), 0); +} + +/* Auxiliary functions to make type signatures for + `operator new' and `operator delete' correspond to + what compiler will be expecting. */ + +tree +coerce_new_type (type) + tree type; +{ + int e1 = 0, e2 = 0; + + if (TREE_CODE (type) == METHOD_TYPE) + type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type))); + if (! same_type_p (TREE_TYPE (type), ptr_type_node)) + e1 = 1, error ("`operator new' must return type `void *'"); + + /* Technically the type must be `size_t', but we may not know + what that is. */ + if (TYPE_ARG_TYPES (type) == NULL_TREE) + e1 = 1, error ("`operator new' takes type `size_t' parameter"); + else if (! same_type_p (TREE_VALUE (TYPE_ARG_TYPES (type)), sizetype)) + e2 = 1, error ("`operator new' takes type `size_t' as first parameter"); + if (e2) + type = build_function_type (ptr_type_node, tree_cons (NULL_TREE, sizetype, TREE_CHAIN (TYPE_ARG_TYPES (type)))); + else if (e1) + type = build_function_type (ptr_type_node, TYPE_ARG_TYPES (type)); + return type; +} + +tree +coerce_delete_type (type) + tree type; +{ + int e1 = 0, e2 = 0; +#if 0 + e3 = 0; +#endif + tree arg_types = TYPE_ARG_TYPES (type); + + if (TREE_CODE (type) == METHOD_TYPE) + { + type = build_function_type (TREE_TYPE (type), TREE_CHAIN (arg_types)); + arg_types = TREE_CHAIN (arg_types); + } + + if (TREE_TYPE (type) != void_type_node) + e1 = 1, error ("`operator delete' must return type `void'"); + + if (arg_types == NULL_TREE + || ! same_type_p (TREE_VALUE (arg_types), ptr_type_node)) + e2 = 1, error ("`operator delete' takes type `void *' as first parameter"); + +#if 0 + if (arg_types + && TREE_CHAIN (arg_types) + && TREE_CHAIN (arg_types) != void_list_node) + { + /* Again, technically this argument must be `size_t', but again + we may not know what that is. */ + tree t2 = TREE_VALUE (TREE_CHAIN (arg_types)); + if (! same_type_p (t2, sizetype)) + e3 = 1, error ("second argument to `operator delete' must be of type `size_t'"); + else if (TREE_CHAIN (TREE_CHAIN (arg_types)) != void_list_node) + { + e3 = 1; + if (TREE_CHAIN (TREE_CHAIN (arg_types))) + error ("too many arguments in declaration of `operator delete'"); + else + error ("`...' invalid in specification of `operator delete'"); + } + } + + if (e3) + arg_types = tree_cons (NULL_TREE, ptr_type_node, + build_tree_list (NULL_TREE, sizetype)); + else if (e3 |= e2) + { + if (arg_types == NULL_TREE) + arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + else + arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types)); + } + else e3 |= e1; +#endif + + if (e2) + arg_types = tree_cons (NULL_TREE, ptr_type_node, + arg_types ? TREE_CHAIN (arg_types): NULL_TREE); + if (e2 || e1) + type = build_function_type (void_type_node, arg_types); + + return type; +} + +extern tree abort_fndecl; + +static void +mark_vtable_entries (decl) + tree decl; +{ + tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl)); + + for (; entries; entries = TREE_CHAIN (entries)) + { + tree fnaddr; + tree fn; + + fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) + : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries))); + + if (TREE_CODE (fnaddr) == NOP_EXPR) + /* RTTI offset. */ + continue; + + fn = TREE_OPERAND (fnaddr, 0); + TREE_ADDRESSABLE (fn) = 1; + if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn)) + { + TREE_OPERAND (fnaddr, 0) = fn = copy_node (fn); + DECL_RTL (fn) = DECL_RTL (abort_fndecl); + mark_used (abort_fndecl); + } + if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn)) + { + DECL_EXTERNAL (fn) = 0; + emit_thunk (fn); + } + mark_used (fn); + } +} + +/* Set DECL up to have the closest approximation of "initialized common" + linkage available. */ + +void +comdat_linkage (decl) + tree decl; +{ + if (flag_weak) + make_decl_one_only (decl); + else if (TREE_CODE (decl) == FUNCTION_DECL || DECL_VIRTUAL_P (decl)) + /* We can just emit functions and vtables statically; it doesn't really + matter if we have multiple copies. */ + TREE_PUBLIC (decl) = 0; + else + { + /* Static data member template instantiations, however, cannot + have multiple copies. */ + if (DECL_INITIAL (decl) == 0 + || DECL_INITIAL (decl) == error_mark_node) + DECL_COMMON (decl) = 1; + else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))) + { + DECL_COMMON (decl) = 1; + DECL_INITIAL (decl) = error_mark_node; + } + else + { + /* We can't do anything useful; leave vars for explicit + instantiation. */ + DECL_EXTERNAL (decl) = 1; + DECL_NOT_REALLY_EXTERN (decl) = 0; + } + } + + if (DECL_LANG_SPECIFIC (decl)) + DECL_COMDAT (decl) = 1; +} + +/* For win32 we also want to put explicit instantiations in + linkonce sections, so that they will be merged with implicit + instantiations; otherwise we get duplicate symbol errors. */ + +void +maybe_make_one_only (decl) + tree decl; +{ + /* We used to say that this was not necessary on targets that support weak + symbols, because the implicit instantiations will defer to the explicit + one. However, that's not actually the case in SVR4; a strong definition + after a weak one is an error. Also, not making explicit + instantiations one_only means that we can end up with two copies of + some template instantiations. */ + if (! supports_one_only ()) + return; + + /* We can't set DECL_COMDAT on functions, or finish_file will think + we can get away with not emitting them if they aren't used. We need + to for variables so that cp_finish_decl will update their linkage, + because their DECL_INITIAL may not have been set properly yet. */ + + make_decl_one_only (decl); + + if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl)) + DECL_COMDAT (decl) = 1; +} + +/* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL, + based on TYPE and other static flags. + + Note that anything public is tagged TREE_PUBLIC, whether + it's public in this file or in another one. */ + +void +import_export_vtable (decl, type, final) + tree decl, type; + int final; +{ + if (DECL_INTERFACE_KNOWN (decl)) + return; + + if (TYPE_FOR_JAVA (type)) + { + TREE_PUBLIC (decl) = 1; + DECL_EXTERNAL (decl) = 1; + DECL_INTERFACE_KNOWN (decl) = 1; + } + else if (CLASSTYPE_INTERFACE_KNOWN (type)) + { + TREE_PUBLIC (decl) = 1; + DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type); + DECL_INTERFACE_KNOWN (decl) = 1; + } + else + { + /* We can only wait to decide if we have real non-inline virtual + functions in our class, or if we come from a template. */ + + int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type); + + if (! found && ! final) + { + tree method; + for (method = TYPE_METHODS (type); method != NULL_TREE; + method = TREE_CHAIN (method)) + if (DECL_VINDEX (method) != NULL_TREE + && ! DECL_THIS_INLINE (method) + && ! DECL_ABSTRACT_VIRTUAL_P (method)) + { + found = 1; + break; + } + } + + if (final || ! found) + { + comdat_linkage (decl); + DECL_EXTERNAL (decl) = 0; + } + else + { + TREE_PUBLIC (decl) = 1; + DECL_EXTERNAL (decl) = 1; + } + } +} + +/* Determine whether or not we want to specifically import or export CTYPE, + using various heuristics. */ + +void +import_export_class (ctype) + tree ctype; +{ + /* -1 for imported, 1 for exported. */ + int import_export = 0; + + if (CLASSTYPE_INTERFACE_KNOWN (ctype)) + return; + + /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma interface, + we will have CLASSTYPE_INTERFACE_ONLY set but not + CLASSTYPE_INTERFACE_KNOWN. In that case, we don't want to use this + heuristic because someone will supply a #pragma implementation + elsewhere, and deducing it here would produce a conflict. */ + if (CLASSTYPE_INTERFACE_ONLY (ctype)) + return; + +#ifdef VALID_MACHINE_TYPE_ATTRIBUTE + /* FIXME this should really use some sort of target-independent macro. */ + if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype))) + import_export = -1; + else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype))) + import_export = 1; +#endif + + /* If we got -fno-implicit-templates, we import template classes that + weren't explicitly instantiated. */ + if (import_export == 0 + && CLASSTYPE_IMPLICIT_INSTANTIATION (ctype) + && ! flag_implicit_templates) + import_export = -1; + + /* Base our import/export status on that of the first non-inline, + non-abstract virtual function, if any. */ + if (import_export == 0 + && TYPE_VIRTUAL_P (ctype) + && ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)) + { + tree method; + for (method = TYPE_METHODS (ctype); method != NULL_TREE; + method = TREE_CHAIN (method)) + { + if (DECL_VINDEX (method) != NULL_TREE + && !DECL_THIS_INLINE (method) + && !DECL_ABSTRACT_VIRTUAL_P (method)) + { + import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1); + break; + } + } + } + +#ifdef MULTIPLE_SYMBOL_SPACES + if (import_export == -1) + import_export = 0; +#endif + + if (import_export) + { + SET_CLASSTYPE_INTERFACE_KNOWN (ctype); + CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = (import_export > 0); + CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0); + } +} + +/* We need to describe to the assembler the relationship between + a vtable and the vtable of the parent class. */ + +static void +output_vtable_inherit (vars) + tree vars; +{ + tree parent; + rtx op[2]; + + op[0] = XEXP (DECL_RTL (vars), 0); /* strip the mem ref */ + + parent = binfo_for_vtable (vars); + + if (parent == TYPE_BINFO (DECL_CONTEXT (vars))) + op[1] = const0_rtx; + else if (parent) + { + parent = TYPE_BINFO_VTABLE (BINFO_TYPE (parent)); + op[1] = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */ + } + else + my_friendly_abort (980826); + + output_asm_insn (".vtable_inherit %c0, %c1", op); +} + +static int +finish_vtable_vardecl (t, data) + tree *t; + void *data ATTRIBUTE_UNUSED; +{ + tree vars = *t; + tree ctype = DECL_CONTEXT (vars); + import_export_class (ctype); + import_export_vtable (vars, ctype, 1); + + if (! DECL_EXTERNAL (vars) + && (DECL_INTERFACE_KNOWN (vars) + || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)) + || (hack_decl_function_context (vars) && TREE_USED (vars))) + && ! TREE_ASM_WRITTEN (vars)) + { + /* Write it out. */ + mark_vtable_entries (vars); + if (TREE_TYPE (DECL_INITIAL (vars)) == 0) + store_init_value (vars, DECL_INITIAL (vars)); + + if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG) + { + /* Mark the VAR_DECL node representing the vtable itself as a + "gratuitous" one, thereby forcing dwarfout.c to ignore it. + It is rather important that such things be ignored because + any effort to actually generate DWARF for them will run + into trouble when/if we encounter code like: + + #pragma interface + struct S { virtual void member (); }; + + because the artificial declaration of the vtable itself (as + manufactured by the g++ front end) will say that the vtable + is a static member of `S' but only *after* the debug output + for the definition of `S' has already been output. This causes + grief because the DWARF entry for the definition of the vtable + will try to refer back to an earlier *declaration* of the + vtable as a static member of `S' and there won't be one. + We might be able to arrange to have the "vtable static member" + attached to the member list for `S' before the debug info for + `S' get written (which would solve the problem) but that would + require more intrusive changes to the g++ front end. */ + + DECL_IGNORED_P (vars) = 1; + } + + /* Always make vtables weak. */ + if (flag_weak) + comdat_linkage (vars); + + rest_of_decl_compilation (vars, NULL_PTR, 1, 1); + + if (flag_vtable_gc) + output_vtable_inherit (vars); + + return 1; + } + else if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars))) + /* We don't know what to do with this one yet. */ + return 0; + + *t = TREE_CHAIN (vars); + return 0; +} + +static int +prune_vtable_vardecl (t, data) + tree *t; + void *data ATTRIBUTE_UNUSED; +{ + *t = TREE_CHAIN (*t); + return 1; +} + +static int +finish_sigtable_vardecl (t, data) + tree *t; + void *data ATTRIBUTE_UNUSED; +{ + /* We don't need to mark sigtable entries as addressable here as is done + for vtables. Since sigtables, unlike vtables, are always written out, + that was already done in build_signature_table_constructor. */ + + rest_of_decl_compilation (*t, NULL_PTR, 1, 1); + *t = TREE_CHAIN (*t); + return 1; +} + +/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an + inline function or template instantiation at end-of-file. */ + +void +import_export_decl (decl) + tree decl; +{ + if (DECL_INTERFACE_KNOWN (decl)) + return; + + if (DECL_TEMPLATE_INSTANTIATION (decl) + || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) + { + DECL_NOT_REALLY_EXTERN (decl) = 1; + if ((DECL_IMPLICIT_INSTANTIATION (decl) + || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) + && (flag_implicit_templates + || (flag_implicit_inline_templates && DECL_THIS_INLINE (decl)))) + { + if (!TREE_PUBLIC (decl)) + /* Templates are allowed to have internal linkage. See + [basic.link]. */ + ; + else + comdat_linkage (decl); + } + else + DECL_NOT_REALLY_EXTERN (decl) = 0; + } + else if (DECL_FUNCTION_MEMBER_P (decl)) + { + tree ctype = DECL_CLASS_CONTEXT (decl); + import_export_class (ctype); + if (CLASSTYPE_INTERFACE_KNOWN (ctype) + && (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl))) + { + DECL_NOT_REALLY_EXTERN (decl) + = ! (CLASSTYPE_INTERFACE_ONLY (ctype) + || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines + && !DECL_VINDEX (decl))); + + /* Always make artificials weak. */ + if (DECL_ARTIFICIAL (decl) && flag_weak) + comdat_linkage (decl); + else + maybe_make_one_only (decl); + } + else + comdat_linkage (decl); + } + else if (DECL_TINFO_FN_P (decl)) + { + tree ctype = TREE_TYPE (DECL_NAME (decl)); + + if (IS_AGGR_TYPE (ctype)) + import_export_class (ctype); + + if (IS_AGGR_TYPE (ctype) && CLASSTYPE_INTERFACE_KNOWN (ctype) + && TYPE_VIRTUAL_P (ctype) + /* If the type is a cv-qualified variant of a type, then we + must emit the tinfo function in this translation unit + since it will not be emitted when the vtable for the type + is output (which is when the unqualified version is + generated). */ + && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype))) + { + DECL_NOT_REALLY_EXTERN (decl) + = ! (CLASSTYPE_INTERFACE_ONLY (ctype) + || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines + && !DECL_VINDEX (decl))); + + /* Always make artificials weak. */ + if (flag_weak) + comdat_linkage (decl); + } + else if (TYPE_BUILT_IN (ctype) + && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype))) + DECL_NOT_REALLY_EXTERN (decl) = 0; + else + comdat_linkage (decl); + } + else + comdat_linkage (decl); + + DECL_INTERFACE_KNOWN (decl) = 1; +} + +tree +build_cleanup (decl) + tree decl; +{ + tree temp; + tree type = TREE_TYPE (decl); + + if (TREE_CODE (type) == ARRAY_TYPE) + temp = decl; + else + { + mark_addressable (decl); + temp = build1 (ADDR_EXPR, build_pointer_type (type), decl); + } + temp = build_delete (TREE_TYPE (temp), temp, + integer_two_node, + LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); + return temp; +} + +extern int parse_time, varconst_time; + +static tree +get_sentry (base) + tree base; +{ + tree sname = get_id_2 ("__sn", base); + /* For struct X foo __attribute__((weak)), there is a counter + __snfoo. Since base is already an assembler name, sname should + be globally unique */ + tree sentry = IDENTIFIER_GLOBAL_VALUE (sname); + if (! sentry) + { + push_obstacks_nochange (); + end_temporary_allocation (); + sentry = build_decl (VAR_DECL, sname, integer_type_node); + TREE_PUBLIC (sentry) = 1; + DECL_ARTIFICIAL (sentry) = 1; + TREE_STATIC (sentry) = 1; + TREE_USED (sentry) = 1; + DECL_COMMON (sentry) = 1; + pushdecl_top_level (sentry); + cp_finish_decl (sentry, NULL_TREE, NULL_TREE, 0, 0); + pop_obstacks (); + } + return sentry; +} + +/* Start the process of running a particular set of global constructors + or destructors. Subroutine of do_[cd]tors. */ + +static void +start_objects (method_type, initp) + int method_type, initp; +{ + tree fnname; + char type[10]; + + /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */ + + if (initp != DEFAULT_INIT_PRIORITY) + { + char joiner; + +#ifdef JOINER + joiner = JOINER; +#else + joiner = '_'; +#endif + + sprintf (type, "%c%c%.5u", method_type, joiner, initp); + } + else + sprintf (type, "%c", method_type); + + fnname = get_file_function_name_long (type); + + start_function (void_list_node, + make_call_declarator (fnname, void_list_node, NULL_TREE, + NULL_TREE), + NULL_TREE, 0); + +#if defined(ASM_OUTPUT_CONSTRUCTOR) && defined(ASM_OUTPUT_DESTRUCTOR) + /* It can be a static function as long as collect2 does not have + to scan the object file to find its ctor/dtor routine. */ + TREE_PUBLIC (current_function_decl) = 0; +#endif + + store_parm_decls (); + pushlevel (0); + clear_last_expr (); + push_momentary (); + expand_start_bindings (0); + + /* We cannot allow these functions to be elided, even if they do not + have external linkage. And, there's no point in deferring + copmilation of thes functions; they're all going to have to be + out anyhow. */ + current_function_cannot_inline + = "static constructors and destructors cannot be inlined"; +} + +/* Finish the process of running a particular set of global constructors + or destructors. Subroutine of do_[cd]tors. */ + +static void +finish_objects (method_type, initp) + int method_type, initp; +{ + char *fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); + + /* Finish up. */ + expand_end_bindings (getdecls (), 1, 0); + poplevel (1, 0, 0); + pop_momentary (); + finish_function (lineno, 0, 0); + + if (initp == DEFAULT_INIT_PRIORITY) + { + if (method_type == 'I') + assemble_constructor (fnname); + else + assemble_destructor (fnname); + } + +#if defined (ASM_OUTPUT_SECTION_NAME) && defined (ASM_OUTPUT_CONSTRUCTOR) + /* If we're using init priority we can't use assemble_*tor, but on ELF + targets we can stick the references into named sections for GNU ld + to collect. */ + else + { + char buf[15]; + sprintf (buf, ".%ctors.%.5u", method_type == 'I' ? 'c' : 'd', + /* invert the numbering so the linker puts us in the proper + order; constructors are run from right to left, and the + linker sorts in increasing order. */ + MAX_INIT_PRIORITY - initp); + named_section (NULL_TREE, buf, 0); + assemble_integer (gen_rtx_SYMBOL_REF (Pmode, fnname), + POINTER_SIZE / BITS_PER_UNIT, 1); + } +#endif +} + +/* The names of the parameters to the function created to handle + initializations and destructions for objects with static storage + duration. */ +#define INITIALIZE_P_IDENTIFIER "__initialize_p" +#define PRIORITY_IDENTIFIER "__priority" + +/* The name of the function we create to handle initializations and + destructions for objects with static storage duration. */ +#define SSDF_IDENTIFIER "__static_initialization_and_destruction" + +/* The declaration for the __INITIALIZE_P argument. */ +static tree initialize_p_decl; + +/* The declaration for the __PRIORITY argument. */ +static tree priority_decl; + +/* The declaration for the static storage duration function. */ +static tree ssdf_decl; + +/* All the static storage duration functions created in this + translation unit. */ +static varray_type ssdf_decls; +static size_t ssdf_decls_used; + +/* A map from priority levels to information about that priority + level. There may be many such levels, so efficient lookup is + important. */ +static splay_tree priority_info_map; + +/* Begins the generation of the function that will handle all + initialization and destruction of objects with static storage + duration. The function generated takes two parameters of type + `int': __INITIALIZE_P and __PRIORITY. If __INITIALIZE_P is + non-zero, it performs initializations. Otherwise, it performs + destructions. It only performs those initializations or + destructions with the indicated __PRIORITY. The generated function + returns no value. + + It is assumed that this function will only be called once per + translation unit. */ + +static void +start_static_storage_duration_function () +{ + static unsigned ssdf_number; + + tree parm_types; + tree type; + char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32]; + + /* Create the identifier for this function. It will be of the form + SSDF_IDENTIFIER_. */ + sprintf (id, "%s_%u", SSDF_IDENTIFIER, ssdf_number++); + if (ssdf_number == 0) + { + /* Overflow occurred. That means there are at least 4 billion + initialization functions. */ + sorry ("too many initialization functions required"); + my_friendly_abort (19990430); + } + + /* Create the parameters. */ + parm_types = void_list_node; + parm_types = perm_tree_cons (NULL_TREE, integer_type_node, parm_types); + parm_types = perm_tree_cons (NULL_TREE, integer_type_node, parm_types); + type = build_function_type (void_type_node, parm_types); + + /* Create the FUNCTION_DECL itself. */ + ssdf_decl = build_lang_decl (FUNCTION_DECL, + get_identifier (id), + type); + TREE_PUBLIC (ssdf_decl) = 0; + DECL_ARTIFICIAL (ssdf_decl) = 1; + + /* Put this function in the list of functions to be called from the + static constructors and destructors. */ + if (!ssdf_decls) + { + VARRAY_TREE_INIT (ssdf_decls, 32, "ssdf_decls"); + + /* Take this opportunity to initialize the map from priority + numbers to information about that priority level. */ + priority_info_map = splay_tree_new (splay_tree_compare_ints, + /*delete_key_fn=*/0, + /*delete_value_fn=*/ + (splay_tree_delete_value_fn) &free); + + /* We always need to generate functions for the + DEFAULT_INIT_PRIORITY so enter it now. That way when we walk + priorities later, we'll be sure to find the + DEFAULT_INIT_PRIORITY. */ + get_priority_info (DEFAULT_INIT_PRIORITY); + } + + if (ssdf_decls_used == ssdf_decls->num_elements) + VARRAY_GROW (ssdf_decls, 2 * ssdf_decls_used); + VARRAY_TREE (ssdf_decls, ssdf_decls_used) = ssdf_decl; + ++ssdf_decls_used; + + /* Create the argument list. */ + initialize_p_decl = build_decl (PARM_DECL, + get_identifier (INITIALIZE_P_IDENTIFIER), + integer_type_node); + DECL_CONTEXT (initialize_p_decl) = ssdf_decl; + DECL_ARG_TYPE (initialize_p_decl) = integer_type_node; + TREE_USED (initialize_p_decl) = 1; + priority_decl = build_decl (PARM_DECL, get_identifier (PRIORITY_IDENTIFIER), + integer_type_node); + DECL_CONTEXT (priority_decl) = ssdf_decl; + DECL_ARG_TYPE (priority_decl) = integer_type_node; + TREE_USED (priority_decl) = 1; + + TREE_CHAIN (initialize_p_decl) = priority_decl; + DECL_ARGUMENTS (ssdf_decl) = initialize_p_decl; + + /* Start the function itself. This is equivalent to declarating the + function as: + + static void __ssdf (int __initialize_p, init __priority_p); + + It is static because we only need to call this function from the + various constructor and destructor functions for this module. */ + start_function (/*specs=*/NULL_TREE, + ssdf_decl, + /*attrs=*/NULL_TREE, + /*pre_parsed_p=*/1); + + /* Set up the scope of the outermost block in the function. */ + store_parm_decls (); + pushlevel (0); + clear_last_expr (); + push_momentary (); + expand_start_bindings (0); + + /* This function must not be deferred because we are depending on + its compilation to tell us what is TREE_SYMBOL_REFERENCED. */ + current_function_cannot_inline + = "static storage duration functions cannot be inlined"; +} + +/* Generate the initialization code for the priority indicated in N. */ + +static int +generate_inits_for_priority (n, data) + splay_tree_node n; + void *data ATTRIBUTE_UNUSED; +{ + int priority = (int) n->key; + priority_info pi = (priority_info) n->value; + + /* For each priority N which has been used generate code which looks + like: + + if (__priority == N) { + if (__initialize_p) + ... + else + ... + } + + We use the sequences we've accumulated to fill in the `...'s. */ + expand_start_cond (build_binary_op (EQ_EXPR, + priority_decl, + build_int_2 (priority, 0)), + /*exit_flag=*/0); + + /* Do the initializations. */ + expand_start_cond (build_binary_op (NE_EXPR, + initialize_p_decl, + integer_zero_node), + /*exit_flag=*/0); + if (pi->initialization_sequence) + { + rtx insns; + + push_to_sequence (pi->initialization_sequence); + insns = gen_sequence (); + end_sequence (); + + emit_insn (insns); + pi->initialization_sequence = NULL_RTX; + pi->initializations_p = 1; + } + + /* Do the destructions. */ + expand_start_else (); + if (pi->destruction_sequence) + { + rtx insns; + + push_to_sequence (pi->destruction_sequence); + insns = gen_sequence (); + end_sequence (); + + emit_insn (insns); + pi->destruction_sequence = NULL_RTX; + pi->destructions_p = 1; + } + + /* Close out the conditionals. */ + expand_end_cond (); + expand_end_cond (); + + /* Don't stop iterating. */ + return 0; +} + +/* Finish the generation of the function which performs initialization + and destruction of objects with static storage duration. After + this point, no more such objects can be created. */ + +static void +finish_static_storage_duration_function () +{ + splay_tree_foreach (priority_info_map, + generate_inits_for_priority, + /*data=*/0); + + /* Close out the function. */ + expand_end_bindings (getdecls (), 1, 0); + poplevel (1, 0, 0); + pop_momentary (); + finish_function (lineno, 0, 0); +} + +/* Return the information about the indicated PRIORITY level. If no + code to handle this level has yet been generated, generate the + appropriate prologue. */ + +static priority_info +get_priority_info (priority) + int priority; +{ + priority_info pi; + splay_tree_node n; + + n = splay_tree_lookup (priority_info_map, + (splay_tree_key) priority); + if (!n) + { + /* Create a new priority information structure, and insert it + into the map. */ + pi = (priority_info) xmalloc (sizeof (struct priority_info_s)); + pi->initialization_sequence = NULL_RTX; + pi->destruction_sequence = NULL_RTX; + pi->initializations_p = 0; + pi->destructions_p = 0; + splay_tree_insert (priority_info_map, + (splay_tree_key) priority, + (splay_tree_value) pi); + } + else + pi = (priority_info) n->value; + + return pi; +} + +/* Generate code to do the static initialization of DECL. The + initialization is INIT. If DECL may be initialized more than once + in different object files, SENTRY is the guard variable to + check. PRIORITY is the priority for the initialization. */ + +static void +do_static_initialization (decl, init, sentry, priority) + tree decl; + tree init; + tree sentry; + int priority; +{ + priority_info pi; + + /* Get the priority information for this PRIORITY, */ + pi = get_priority_info (priority); + if (!pi->initialization_sequence) + start_sequence (); + else + push_to_sequence (pi->initialization_sequence); + + /* Tell the debugger that we are at the location of the static + variable in question. */ + emit_note (input_filename, lineno); + + /* If there's a SENTRY, we only do the initialization if it is + zero, i.e., if we are the first to initialize it. */ + if (sentry) + expand_start_cond (build_binary_op (EQ_EXPR, + build_unary_op (PREINCREMENT_EXPR, + sentry, + /*noconvert=*/0), + integer_one_node), + /*exit_flag=*/0); + + /* Prepare a binding level for temporaries created during the + initialization. */ + expand_start_target_temps (); + + if (IS_AGGR_TYPE (TREE_TYPE (decl)) + || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) + expand_aggr_init (decl, init, 0); + else if (TREE_CODE (init) == TREE_VEC) + expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0), + TREE_VEC_ELT (init, 1), + TREE_VEC_ELT (init, 2), 0), + const0_rtx, VOIDmode, EXPAND_NORMAL); + else + expand_assignment (decl, init, 0, 0); + + /* The expression might have involved increments and decrements. */ + emit_queue (); + + /* Cleanup any temporaries needed for the initial value. */ + expand_end_target_temps (); + + /* Cleanup any deferred pops from function calls. This would be done + by expand_end_cond, but we also need it when !SENTRY, since we are + constructing these sequences by parts. */ + do_pending_stack_adjust (); + + /* Close the conditional opened above. */ + if (sentry) + expand_end_cond (); + + /* Save the sequence for later use. */ + pi->initialization_sequence = get_insns (); + end_sequence (); +} + +/* Generate code to do the static destruction of DECL. If DECL may be + initialized more than once in different object files, SENTRY is the + guard variable to check. PRIORITY is the priority for the + destruction. */ + +static void +do_static_destruction (decl, sentry, priority) + tree decl; + tree sentry; + int priority; +{ + rtx new_insns; + priority_info pi; + + /* If we don't need a destructor, there's nothing to do. */ + if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl))) + return; + + /* Get the priority information for this PRIORITY, */ + pi = get_priority_info (priority); + if (!pi->destruction_sequence) + start_sequence (); + else + push_to_sequence (pi->destruction_sequence); + + /* Start a new sequence to handle just this destruction. */ + start_sequence (); + + /* Tell the debugger that we are at the location of the static + variable in question. */ + emit_note (input_filename, lineno); + + /* If there's a SENTRY, we only do the destruction if it is one, + i.e., if we are the last to destroy it. */ + if (sentry) + expand_start_cond (build_binary_op (EQ_EXPR, + build_unary_op (PREDECREMENT_EXPR, + sentry, + /*nonconvert=*/1), + integer_zero_node), + /*exit_flag=*/0); + + /* Actually to the destruction. */ + expand_expr_stmt (build_cleanup (decl)); + + /* Cleanup any deferred pops from function calls. This would be done + by expand_end_cond, but we also need it when !SENTRY, since we are + constructing these sequences by parts. */ + do_pending_stack_adjust (); + + /* Close the conditional opened above. */ + if (sentry) + expand_end_cond (); + + /* Insert the NEW_INSNS before the current insns. (Destructions are + run in reverse order of initializations.) */ + new_insns = gen_sequence (); + end_sequence (); + if (pi->destruction_sequence) + emit_insn_before (new_insns, pi->destruction_sequence); + else + emit_insn (new_insns); + + /* Save the sequence for later use. */ + pi->destruction_sequence = get_insns (); + end_sequence (); +} + +/* Add code to the static storage duration function that will handle + DECL (a static variable that needs initializing and/or destruction) + with the indicated PRIORITY. If DECL needs initializing, INIT is + the initializer. */ + +static void +do_static_initialization_and_destruction (decl, init) + tree decl; + tree init; +{ + tree sentry = NULL_TREE; + int priority; + + /* Deal gracefully with error. */ + if (decl == error_mark_node) + return; + + /* The only things that can be initialized are variables. */ + my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420); + + /* If this object is not defined, we don't need to do anything + here. */ + if (DECL_EXTERNAL (decl)) + return; + + /* Also, if the initializer already contains errors, we can bail out + now. */ + if (init && TREE_CODE (init) == TREE_LIST + && value_member (error_mark_node, init)) + return; + + /* Trick the compiler into thinking we are at the file and line + where DECL was declared so that error-messages make sense, and so + that the debugger will show somewhat sensible file and line + information. */ + input_filename = DECL_SOURCE_FILE (decl); + lineno = DECL_SOURCE_LINE (decl); + + /* Because of: + + [class.access.spec] + + Access control for implicit calls to the constructors, + the conversion functions, or the destructor called to + create and destroy a static data member is performed as + if these calls appeared in the scope of the member's + class. + + we pretend we are in a static member function of the class of + which the DECL is a member. */ + if (member_p (decl)) + { + DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl); + DECL_STATIC_FUNCTION_P (current_function_decl) = 1; + } + + /* We need a sentry if this is an object with external linkage that + might be initialized in more than one place. */ + if (TREE_PUBLIC (decl) && (DECL_COMMON (decl) + || DECL_ONE_ONLY (decl) + || DECL_WEAK (decl))) + sentry = get_sentry (DECL_ASSEMBLER_NAME (decl)); + + /* Generate the code to actually do the intialization and + destruction. */ + priority = DECL_INIT_PRIORITY (decl); + if (!priority) + priority = DEFAULT_INIT_PRIORITY; + do_static_initialization (decl, init, sentry, priority); + do_static_destruction (decl, sentry, priority); + + /* Now that we're done with DECL we don't need to pretend to be a + member of its class any longer. */ + DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE; + DECL_STATIC_FUNCTION_P (current_function_decl) = 0; +} + +/* Generate a static constructor (if CONSTRUCTOR_P) or destructor + (otherwise) that will initialize all gobal objects with static + storage duration having the indicated PRIORITY. */ + +static void +generate_ctor_or_dtor_function (constructor_p, priority) + int constructor_p; + int priority; +{ + char function_key; + tree arguments; + size_t i; + + /* We use `I' to indicate initialization and `D' to indicate + destruction. */ + if (constructor_p) + function_key = 'I'; + else + function_key = 'D'; + + /* Begin the function. */ + start_objects (function_key, priority); + + /* Call the static storage duration function with appropriate + arguments. */ + for (i = 0; i < ssdf_decls_used; ++i) + { + arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0), + NULL_TREE); + arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0), + arguments); + expand_expr_stmt (build_function_call (VARRAY_TREE (ssdf_decls, i), + arguments)); + } + + /* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in + calls to any functions marked with attributes indicating that + they should be called at initialization- or destruction-time. */ + if (priority == DEFAULT_INIT_PRIORITY) + { + tree fns; + + for (fns = constructor_p ? static_ctors : static_dtors; + fns; + fns = TREE_CHAIN (fns)) + expand_expr_stmt (build_function_call (TREE_VALUE (fns), NULL_TREE)); + } + + /* Close out the function. */ + finish_objects (function_key, priority); +} + +/* Generate constructor and destructor functions for the priority + indicated by N. */ + +static int +generate_ctor_and_dtor_functions_for_priority (n, data) + splay_tree_node n; + void *data ATTRIBUTE_UNUSED; +{ + int priority = (int) n->key; + priority_info pi = (priority_info) n->value; + + /* Generate the functions themselves, but only if they are really + needed. */ + if (pi->initializations_p + || (priority == DEFAULT_INIT_PRIORITY && static_ctors)) + generate_ctor_or_dtor_function (/*constructor_p=*/1, + priority); + if (pi->destructions_p + || (priority == DEFAULT_INIT_PRIORITY && static_dtors)) + generate_ctor_or_dtor_function (/*constructor_p=*/0, + priority); + + /* Keep iterating. */ + return 0; +} + +/* This routine is called from the last rule in yyparse (). + Its job is to create all the code needed to initialize and + destroy the global aggregates. We do the destruction + first, since that way we only need to reverse the decls once. */ + +void +finish_file () +{ + extern int lineno; + int start_time, this_time; + tree vars; + int reconsider; + size_t i; + + at_eof = 1; + + /* Bad parse errors. Just forget about it. */ + if (! global_bindings_p () || current_class_type || decl_namespace_list) + return; + + start_time = get_run_time (); + + /* Otherwise, GDB can get confused, because in only knows + about source for LINENO-1 lines. */ + lineno -= 1; + + interface_unknown = 1; + interface_only = 0; + + /* We now have to write out all the stuff we put off writing out. + These include: + + o Template specializations that we have not yet instantiated, + but which are needed. + o Initialization and destruction for non-local objects with + static storage duration. (Local objects with static storage + duration are initialized when their scope is first entered, + and are cleaned up via atexit.) + o Virtual function tables. + + All of these may cause others to be needed. For example, + instantiating one function may cause another to be needed, and + generating the intiailzer for an object may cause templates to be + instantiated, etc., etc. */ + + this_time = get_run_time (); + parse_time -= this_time - start_time; + varconst_time += this_time - start_time; + start_time = get_run_time (); + permanent_allocation (1); + + do + { + /* Non-zero if we need a static storage duration function on + this iteration through the loop. */ + int need_ssdf_p = 0; + + reconsider = 0; + + /* If there are templates that we've put off instantiating, do + them now. */ + instantiate_pending_templates (); + + /* Write out signature-tables and virtual tables as required. + Note that writing out the virtual table for a template class + may cause the instantiation of members of that class. */ + if (flag_handle_signatures + && walk_globals (sigtable_decl_p, + finish_sigtable_vardecl, + /*data=*/0)) + reconsider = 1; + if (walk_globals (vtable_decl_p, + finish_vtable_vardecl, + /*data=*/0)) + reconsider = 1; + + /* The list of objects with static storage duration is built up + in reverse order, so we reverse it here. We also clear + STATIC_AGGREGATES so that any new aggregates added during the + initialization of these will be initialized in the correct + order when we next come around the loop. */ + vars = nreverse (static_aggregates); + static_aggregates = NULL_TREE; + while (vars) + { + if (! TREE_ASM_WRITTEN (TREE_VALUE (vars))) + rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1); + if (!need_ssdf_p) + { + /* We need to start a new initialization function each + time through the loop. That's because we need to + know which vtables have been referenced, and + TREE_SYMBOL_REFERENCED isn't computed until a + function is finished, and written out. That's a + deficiency in the back-end. When this is fixed, + these initialization functions could all become + inline, with resulting performance improvements. */ + start_static_storage_duration_function (); + need_ssdf_p = 1; + } + + do_static_initialization_and_destruction (TREE_VALUE (vars), + TREE_PURPOSE (vars)); + reconsider = 1; + vars = TREE_CHAIN (vars); + } + + /* Finish up the static storage duration function for this + round. */ + if (need_ssdf_p) + finish_static_storage_duration_function (); + + /* Go through the various inline functions, and see if any need + synthesizing. */ + for (i = 0; i < saved_inlines_used; ++i) + { + tree decl = VARRAY_TREE (saved_inlines, i); + import_export_decl (decl); + if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) + && TREE_USED (decl) + && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl))) + { + /* Even though we're already at the top-level, we push + there again. That way, when we pop back a few lines + hence, all of our state is restored. Otherwise, + finish_function doesn't clean things up, and we end + up with CURRENT_FUNCTION_DECL set. */ + push_to_top_level (); + if (DECL_TINFO_FN_P (decl)) + synthesize_tinfo_fn (decl); + else + synthesize_method (decl); + pop_from_top_level (); + reconsider = 1; + } + } + + /* Mark all functions that might deal with exception-handling as + referenced. */ + mark_all_runtime_matches (); + + /* We lie to the back-end, pretending that some functions are + not defined when they really are. This keeps these functions + from being put out unncessarily. But, we must stop lying + when the functions are referenced, or if they are not comdat + since they need to be put out now. */ + for (i = 0; i < saved_inlines_used; ++i) + { + tree decl = VARRAY_TREE (saved_inlines, i); + + if (DECL_NOT_REALLY_EXTERN (decl) + && DECL_INITIAL (decl) + && (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) + || !DECL_COMDAT (decl))) + DECL_EXTERNAL (decl) = 0; + } + + if (saved_inlines_used + && wrapup_global_declarations (&VARRAY_TREE (saved_inlines, 0), + saved_inlines_used)) + reconsider = 1; + if (walk_namespaces (wrapup_globals_for_namespace, /*data=*/0)) + reconsider = 1; + + /* Static data members are just like namespace-scope globals. */ + for (i = 0; i < pending_statics_used; ++i) + { + tree decl = VARRAY_TREE (pending_statics, i); + if (TREE_ASM_WRITTEN (decl)) + continue; + import_export_decl (decl); + if (DECL_NOT_REALLY_EXTERN (decl) && ! DECL_IN_AGGR_P (decl)) + DECL_EXTERNAL (decl) = 0; + } + if (pending_statics + && wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0), + pending_statics_used)) + reconsider = 1; + } + while (reconsider); + + /* We give C linkage to static constructors and destructors. */ + push_lang_context (lang_name_c); + + /* Generate initialization and destruction functions for all + priorities for which they are required. */ + if (priority_info_map) + splay_tree_foreach (priority_info_map, + generate_ctor_and_dtor_functions_for_priority, + /*data=*/0); + + /* We're done with the splay-tree now. */ + if (priority_info_map) + splay_tree_delete (priority_info_map); + + /* We're done with static constructors, so we can go back to "C++" + linkage now. */ + pop_lang_context (); + + /* Now delete from the chain of variables all virtual function tables. + We output them all ourselves, because each will be treated + specially. */ + walk_globals (vtable_decl_p, prune_vtable_vardecl, /*data=*/0); + + /* Now, issue warnings about static, but not defined, functions, + etc. */ + walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider); + + finish_repo (); + + this_time = get_run_time (); + parse_time -= this_time - start_time; + varconst_time += this_time - start_time; + + if (flag_detailed_statistics) + { + dump_tree_statistics (); + dump_time_statistics (); + } +} + +/* This is something of the form 'A()()()()()+1' that has turned out to be an + expr. Since it was parsed like a type, we need to wade through and fix + that. Unfortunately, since operator() is left-associative, we can't use + tail recursion. In the above example, TYPE is `A', and DECL is + `()()()()()'. + + Maybe this shouldn't be recursive, but how often will it actually be + used? (jason) */ + +tree +reparse_absdcl_as_expr (type, decl) + tree type, decl; +{ + /* do build_functional_cast (type, NULL_TREE) at bottom */ + if (TREE_OPERAND (decl, 0) == NULL_TREE) + return build_functional_cast (type, NULL_TREE); + + /* recurse */ + decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0)); + + decl = build_x_function_call (decl, NULL_TREE, current_class_ref); + + if (TREE_CODE (decl) == CALL_EXPR + && (! TREE_TYPE (decl) + || TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE)) + decl = require_complete_type (decl); + + return decl; +} + +/* This is something of the form `int ((int)(int)(int)1)' that has turned + out to be an expr. Since it was parsed like a type, we need to wade + through and fix that. Since casts are right-associative, we are + reversing the order, so we don't have to recurse. + + In the above example, DECL is the `(int)(int)(int)', and EXPR is the + `1'. */ + +tree +reparse_absdcl_as_casts (decl, expr) + tree decl, expr; +{ + tree type; + + if (TREE_CODE (expr) == CONSTRUCTOR + && TREE_TYPE (expr) == 0) + { + type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1))); + decl = TREE_OPERAND (decl, 0); + + if (IS_SIGNATURE (type)) + { + error ("cast specifies signature type"); + return error_mark_node; + } + + expr = digest_init (type, expr, (tree *) 0); + if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) + { + int failure = complete_array_type (type, expr, 1); + if (failure) + my_friendly_abort (78); + } + } + + while (decl) + { + type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1))); + decl = TREE_OPERAND (decl, 0); + expr = build_c_cast (type, expr); + } + + if (warn_old_style_cast && ! in_system_header + && current_lang_name != lang_name_c) + warning ("use of old-style cast"); + + return expr; +} + +/* Given plain tree nodes for an expression, build up the full semantics. */ + +tree +build_expr_from_tree (t) + tree t; +{ + if (t == NULL_TREE || t == error_mark_node) + return t; + + switch (TREE_CODE (t)) + { + case IDENTIFIER_NODE: + return do_identifier (t, 0, NULL_TREE); + + case LOOKUP_EXPR: + if (LOOKUP_EXPR_GLOBAL (t)) + return do_scoped_id (TREE_OPERAND (t, 0), 0); + else + return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE); + + case TEMPLATE_ID_EXPR: + return (lookup_template_function + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1)))); + + case INDIRECT_REF: + return build_x_indirect_ref + (build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *"); + + case CAST_EXPR: + return build_functional_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case REINTERPRET_CAST_EXPR: + return build_reinterpret_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case CONST_CAST_EXPR: + return build_const_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case DYNAMIC_CAST_EXPR: + return build_dynamic_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case STATIC_CAST_EXPR: + return build_static_cast + (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); + + case PREDECREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case NEGATE_EXPR: + case BIT_NOT_EXPR: + case ABS_EXPR: + case TRUTH_NOT_EXPR: + case ADDR_EXPR: + case CONVERT_EXPR: /* Unary + */ + if (TREE_TYPE (t)) + return t; + return build_x_unary_op (TREE_CODE (t), + build_expr_from_tree (TREE_OPERAND (t, 0))); + + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + case EXACT_DIV_EXPR: + case BIT_AND_EXPR: + case BIT_ANDTC_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case TRUNC_MOD_EXPR: + case FLOOR_MOD_EXPR: + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + case TRUTH_AND_EXPR: + case TRUTH_OR_EXPR: + case RSHIFT_EXPR: + case LSHIFT_EXPR: + case RROTATE_EXPR: + case LROTATE_EXPR: + case EQ_EXPR: + case NE_EXPR: + case MAX_EXPR: + case MIN_EXPR: + case LE_EXPR: + case GE_EXPR: + case LT_EXPR: + case GT_EXPR: + case MEMBER_REF: + return build_x_binary_op + (TREE_CODE (t), + build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1))); + + case DOTSTAR_EXPR: + return build_m_component_ref + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1))); + + case SCOPE_REF: + return build_offset_ref (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)); + + case ARRAY_REF: + if (TREE_OPERAND (t, 0) == NULL_TREE) + /* new-type-id */ + return build_parse_node (ARRAY_REF, NULL_TREE, + build_expr_from_tree (TREE_OPERAND (t, 1))); + return grok_array_decl (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1))); + + case SIZEOF_EXPR: + case ALIGNOF_EXPR: + { + tree r = build_expr_from_tree (TREE_OPERAND (t, 0)); + if (TREE_CODE_CLASS (TREE_CODE (r)) != 't') + r = TREE_TYPE (r); + return TREE_CODE (t) == SIZEOF_EXPR ? c_sizeof (r) : c_alignof (r); + } + + case MODOP_EXPR: + return build_x_modify_expr + (build_expr_from_tree (TREE_OPERAND (t, 0)), + TREE_CODE (TREE_OPERAND (t, 1)), + build_expr_from_tree (TREE_OPERAND (t, 2))); + + case ARROW_EXPR: + return build_x_arrow + (build_expr_from_tree (TREE_OPERAND (t, 0))); + + case NEW_EXPR: + return build_new + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1)), + build_expr_from_tree (TREE_OPERAND (t, 2)), + NEW_EXPR_USE_GLOBAL (t)); + + case DELETE_EXPR: + return delete_sanity + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1)), + DELETE_EXPR_USE_VEC (t), DELETE_EXPR_USE_GLOBAL (t)); + + case COMPOUND_EXPR: + if (TREE_OPERAND (t, 1) == NULL_TREE) + return build_x_compound_expr + (build_expr_from_tree (TREE_OPERAND (t, 0))); + else + my_friendly_abort (42); + + case METHOD_CALL_EXPR: + if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF) + { + tree ref = TREE_OPERAND (t, 0); + return build_scoped_method_call + (build_expr_from_tree (TREE_OPERAND (t, 1)), + build_expr_from_tree (TREE_OPERAND (ref, 0)), + TREE_OPERAND (ref, 1), + build_expr_from_tree (TREE_OPERAND (t, 2))); + } + else + { + tree fn = TREE_OPERAND (t, 0); + + /* We can get a TEMPLATE_ID_EXPR here on code like: + + x->f<2>(); + + so we must resolve that. However, we can also get things + like a BIT_NOT_EXPR here, when referring to a destructor, + and things like that are not correctly resolved by + build_expr_from_tree. So, just use build_expr_from_tree + when we really need it. */ + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) + fn = lookup_template_function + (TREE_OPERAND (fn, 0), + build_expr_from_tree (TREE_OPERAND (fn, 1))); + + return build_method_call + (build_expr_from_tree (TREE_OPERAND (t, 1)), + fn, + build_expr_from_tree (TREE_OPERAND (t, 2)), + NULL_TREE, LOOKUP_NORMAL); + } + + case CALL_EXPR: + if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF) + { + tree ref = TREE_OPERAND (t, 0); + return build_member_call + (build_expr_from_tree (TREE_OPERAND (ref, 0)), + TREE_OPERAND (ref, 1), + build_expr_from_tree (TREE_OPERAND (t, 1))); + } + else + { + tree name = TREE_OPERAND (t, 0); + tree id; + tree args = build_expr_from_tree (TREE_OPERAND (t, 1)); + if (args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR + && !LOOKUP_EXPR_GLOBAL (name) + && TREE_CODE ((id = TREE_OPERAND (name, 0))) == IDENTIFIER_NODE + && (!current_class_type + || !lookup_member (current_class_type, id, 0, 0))) + { + /* Do Koenig lookup if there are no class members. */ + name = do_identifier (id, 0, args); + } + else if (TREE_CODE (name) == TEMPLATE_ID_EXPR + || ! really_overloaded_fn (name)) + name = build_expr_from_tree (name); + return build_x_function_call (name, args, current_class_ref); + } + + case COND_EXPR: + return build_x_conditional_expr + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1)), + build_expr_from_tree (TREE_OPERAND (t, 2))); + + case TREE_LIST: + { + tree purpose, value, chain; + + if (t == void_list_node) + return t; + + purpose = TREE_PURPOSE (t); + if (purpose) + purpose = build_expr_from_tree (purpose); + value = TREE_VALUE (t); + if (value) + value = build_expr_from_tree (value); + chain = TREE_CHAIN (t); + if (chain && chain != void_type_node) + chain = build_expr_from_tree (chain); + return expr_tree_cons (purpose, value, chain); + } + + case COMPONENT_REF: + { + tree object = build_expr_from_tree (TREE_OPERAND (t, 0)); + tree field = TREE_OPERAND (t, 1); + + /* We use a COMPONENT_REF to indicate things of the form `x.b' + and `x.A::b'. We must distinguish between those cases + here. */ + if (TREE_CODE (field) == SCOPE_REF) + return build_object_ref (object, + TREE_OPERAND (field, 0), + TREE_OPERAND (field, 1)); + else + return build_x_component_ref (object, field, + NULL_TREE, 1); + } + + case THROW_EXPR: + return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0))); + + case CONSTRUCTOR: + { + tree r; + + /* digest_init will do the wrong thing if we let it. */ + if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) + return t; + + r = build_nt (CONSTRUCTOR, NULL_TREE, + build_expr_from_tree (CONSTRUCTOR_ELTS (t))); + TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t); + + if (TREE_TYPE (t)) + return digest_init (TREE_TYPE (t), r, 0); + return r; + } + + case TYPEID_EXPR: + if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't') + return get_typeid (TREE_OPERAND (t, 0)); + return build_x_typeid (build_expr_from_tree (TREE_OPERAND (t, 0))); + + case VAR_DECL: + return convert_from_reference (t); + + default: + return t; + } +} + +/* This is something of the form `int (*a)++' that has turned out to be an + expr. It was only converted into parse nodes, so we need to go through + and build up the semantics. Most of the work is done by + build_expr_from_tree, above. + + In the above example, TYPE is `int' and DECL is `*a'. */ + +tree +reparse_decl_as_expr (type, decl) + tree type, decl; +{ + decl = build_expr_from_tree (decl); + if (type) + return build_functional_cast (type, build_expr_list (NULL_TREE, decl)); + else + return decl; +} + +/* This is something of the form `int (*a)' that has turned out to be a + decl. It was only converted into parse nodes, so we need to do the + checking that make_{pointer,reference}_declarator do. */ + +tree +finish_decl_parsing (decl) + tree decl; +{ + extern int current_class_depth; + + switch (TREE_CODE (decl)) + { + case IDENTIFIER_NODE: + return decl; + case INDIRECT_REF: + return make_pointer_declarator + (NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0))); + case ADDR_EXPR: + return make_reference_declarator + (NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0))); + case BIT_NOT_EXPR: + TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0)); + return decl; + case SCOPE_REF: + push_nested_class (TREE_TYPE (TREE_OPERAND (decl, 0)), 3); + TREE_COMPLEXITY (decl) = current_class_depth; + return decl; + case ARRAY_REF: + TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0)); + return decl; + case TREE_LIST: + /* For attribute handling. */ + TREE_VALUE (decl) = finish_decl_parsing (TREE_VALUE (decl)); + return decl; + default: + my_friendly_abort (5); + return NULL_TREE; + } +} + +tree +check_cp_case_value (value) + tree value; +{ + if (value == NULL_TREE) + return value; + + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + STRIP_TYPE_NOPS (value); + + if (TREE_READONLY_DECL_P (value)) + { + value = decl_constant_value (value); + STRIP_TYPE_NOPS (value); + } + value = fold (value); + + if (TREE_CODE (value) != INTEGER_CST + && value != error_mark_node) + { + cp_error ("case label `%E' does not reduce to an integer constant", + value); + value = error_mark_node; + } + else + /* Promote char or short to int. */ + value = default_conversion (value); + + constant_expression_warning (value); + + return value; +} + +/* Return 1 if root encloses child. */ + +static int +is_namespace_ancestor (root, child) + tree root, child; +{ + if (root == child) + return 1; + if (root == global_namespace) + return 1; + if (child == global_namespace) + return 0; + return is_namespace_ancestor (root, CP_DECL_CONTEXT (child)); +} + + +/* Return the namespace that is the common ancestor + of two given namespaces. */ + +tree +namespace_ancestor (ns1, ns2) + tree ns1, ns2; +{ + if (is_namespace_ancestor (ns1, ns2)) + return ns1; + return namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2); +} + +/* Insert used into the using list of user. Set indirect_flag if this + directive is not directly from the source. Also find the common + ancestor and let our users know about the new namespace */ +static void +add_using_namespace (user, used, indirect) + tree user; + tree used; + int indirect; +{ + tree t; + /* Using oneself is a no-op. */ + if (user == used) + return; + my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380); + my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380); + /* Check if we already have this. */ + t = purpose_member (used, DECL_NAMESPACE_USING (user)); + if (t != NULL_TREE) + { + if (!indirect) + /* Promote to direct usage. */ + TREE_INDIRECT_USING (t) = 0; + return; + } + + /* Add used to the user's using list. */ + DECL_NAMESPACE_USING (user) + = perm_tree_cons (used, namespace_ancestor (user, used), + DECL_NAMESPACE_USING (user)); + + TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect; + + /* Add user to the used's users list. */ + DECL_NAMESPACE_USERS (used) + = perm_tree_cons (user, 0, DECL_NAMESPACE_USERS (used)); + + /* Recursively add all namespaces used. */ + for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t)) + /* indirect usage */ + add_using_namespace (user, TREE_PURPOSE (t), 1); + + /* Tell everyone using us about the new used namespaces. */ + for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t)) + add_using_namespace (TREE_PURPOSE (t), used, 1); +} + +/* Combines two sets of overloaded functions into an OVERLOAD chain, removing + duplicates. The first list becomes the tail of the result. + + The algorithm is O(n^2). We could get this down to O(n log n) by + doing a sort on the addresses of the functions, if that becomes + necessary. */ + +static tree +merge_functions (s1, s2) + tree s1; + tree s2; +{ + for (; s2; s2 = OVL_NEXT (s2)) + { + tree fn = OVL_CURRENT (s2); + if (! ovl_member (fn, s1)) + s1 = build_overload (fn, s1); + } + return s1; +} + +/* This should return an error not all definitions define functions. + It is not an error if we find two functions with exactly the + same signature, only if these are selected in overload resolution. + old is the current set of bindings, new the freshly-found binding. + XXX Do we want to give *all* candidates in case of ambiguity? + XXX In what way should I treat extern declarations? + XXX I don't want to repeat the entire duplicate_decls here */ + +static tree +ambiguous_decl (name, old, new, flags) + tree name; + tree old; + tree new; + int flags; +{ + tree val, type; + my_friendly_assert (old != NULL_TREE, 393); + /* Copy the value. */ + val = BINDING_VALUE (new); + if (val) + switch (TREE_CODE (val)) + { + case TEMPLATE_DECL: + /* If we expect types or namespaces, and not templates, + or this is not a template class. */ + if (LOOKUP_QUALIFIERS_ONLY (flags) + && !DECL_CLASS_TEMPLATE_P (val)) + val = NULL_TREE; + break; + case TYPE_DECL: + if (LOOKUP_NAMESPACES_ONLY (flags)) + val = NULL_TREE; + break; + case NAMESPACE_DECL: + if (LOOKUP_TYPES_ONLY (flags)) + val = NULL_TREE; + break; + default: + if (LOOKUP_QUALIFIERS_ONLY (flags)) + val = NULL_TREE; + } + + if (!BINDING_VALUE (old)) + BINDING_VALUE (old) = val; + else if (val && val != BINDING_VALUE (old)) + { + if (is_overloaded_fn (BINDING_VALUE (old)) + && is_overloaded_fn (val)) + { + BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old), + val); + } + else + { + /* Some declarations are functions, some are not. */ + if (flags & LOOKUP_COMPLAIN) + { + /* If we've already given this error for this lookup, + BINDING_VALUE (old) is error_mark_node, so let's not + repeat ourselves. */ + if (BINDING_VALUE (old) != error_mark_node) + { + cp_error ("use of `%D' is ambiguous", name); + cp_error_at (" first declared as `%#D' here", + BINDING_VALUE (old)); + } + cp_error_at (" also declared as `%#D' here", val); + } + return error_mark_node; + } + } + /* ... and copy the type. */ + type = BINDING_TYPE (new); + if (LOOKUP_NAMESPACES_ONLY (flags)) + type = NULL_TREE; + if (!BINDING_TYPE (old)) + BINDING_TYPE (old) = type; + else if (type && BINDING_TYPE (old) != type) + { + if (flags & LOOKUP_COMPLAIN) + { + cp_error ("`%D' denotes an ambiguous type",name); + cp_error_at (" first type here", BINDING_TYPE (old)); + cp_error_at (" other type here", type); + } + } + return old; +} + +/* Add the bindings of name in used namespaces to val. + The using list is defined by usings, and the lookup goes to scope. + Returns zero on errors. */ + +int +lookup_using_namespace (name, val, usings, scope, flags) + tree name, val, usings, scope; + int flags; +{ + tree iter; + tree val1; + /* Iterate over all used namespaces in current, searching for using + directives of scope. */ + for (iter = usings; iter; iter = TREE_CHAIN (iter)) + if (TREE_VALUE (iter) == scope) + { + val1 = binding_for_name (name, TREE_PURPOSE (iter)); + /* Resolve ambiguities. */ + val = ambiguous_decl (name, val, val1, flags); + } + return val != error_mark_node; +} + +/* [namespace.qual] + Excepts the name to lookup and its qualifying scope. + Returns the name/type pair found into the CPLUS_BINDING result, + or 0 on error. */ + +int +qualified_lookup_using_namespace (name, scope, result, flags) + tree name; + tree scope; + tree result; + int flags; +{ + /* Maintain a list of namespaces visited... */ + tree seen = NULL_TREE; + /* ... and a list of namespace yet to see. */ + tree todo = NULL_TREE; + tree usings; + while (scope && (result != error_mark_node)) + { + seen = temp_tree_cons (scope, NULL_TREE, seen); + result = ambiguous_decl (name, result, + binding_for_name (name, scope), flags); + if (!BINDING_VALUE (result) && !BINDING_TYPE (result)) + /* Consider using directives. */ + for (usings = DECL_NAMESPACE_USING (scope); usings; + usings = TREE_CHAIN (usings)) + /* If this was a real directive, and we have not seen it. */ + if (!TREE_INDIRECT_USING (usings) + && !purpose_member (TREE_PURPOSE (usings), seen)) + todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo); + if (todo) + { + scope = TREE_PURPOSE (todo); + todo = TREE_CHAIN (todo); + } + else + scope = NULL_TREE; /* If there never was a todo list. */ + } + return result != error_mark_node; +} + +/* [namespace.memdef]/2 */ + +/* Set the context of a declaration to scope. Complain if we are not + outside scope. */ + +void +set_decl_namespace (decl, scope, friendp) + tree decl; + tree scope; + int friendp; +{ + tree old; + if (scope == std_node) + scope = global_namespace; + /* Get rid of namespace aliases. */ + scope = ORIGINAL_NAMESPACE (scope); + + /* It is ok for friends to be qualified in parallel space. */ + if (!friendp && !is_namespace_ancestor (current_namespace, scope)) + cp_error ("declaration of `%D' not in a namespace surrounding `%D'", + decl, scope); + DECL_CONTEXT (decl) = FROB_CONTEXT (scope); + if (scope != current_namespace) + { + /* See whether this has been declared in the namespace. */ + old = namespace_binding (DECL_NAME (decl), scope); + if (!old) + /* No old declaration at all. */ + goto complain; + if (!is_overloaded_fn (decl)) + /* Don't compare non-function decls with decls_match here, + since it can't check for the correct constness at this + point. pushdecl will find those errors later. */ + return; + /* Since decl is a function, old should contain a function decl. */ + if (!is_overloaded_fn (old)) + goto complain; + if (processing_template_decl || processing_specialization) + /* We have not yet called push_template_decl to turn the + FUNCTION_DECL into a TEMPLATE_DECL, so the declarations + won't match. But, we'll check later, when we construct the + template. */ + return; + for (; old; old = OVL_NEXT (old)) + if (decls_match (decl, OVL_CURRENT (old))) + return; + } + else + return; + complain: + cp_error ("`%D' should have been declared inside `%D'", + decl, scope); +} + +/* Compute the namespace where a declaration is defined. */ + +static tree +decl_namespace (decl) + tree decl; +{ + while (DECL_CONTEXT (decl)) + { + decl = DECL_CONTEXT (decl); + if (TREE_CODE (decl) == NAMESPACE_DECL) + return decl; + if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't') + decl = TYPE_STUB_DECL (decl); + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 390); + } + + return global_namespace; +} + +/* Return the namespace where the current declaration is declared. */ + +tree +current_decl_namespace () +{ + tree result; + /* If we have been pushed into a different namespace, use it. */ + if (decl_namespace_list) + return TREE_PURPOSE (decl_namespace_list); + + if (current_class_type) + result = decl_namespace (TYPE_STUB_DECL (current_class_type)); + else if (current_function_decl) + result = decl_namespace (current_function_decl); + else + result = current_namespace; + return result; +} + +/* Temporarily set the namespace for the current declaration. */ + +void +push_decl_namespace (decl) + tree decl; +{ + if (TREE_CODE (decl) != NAMESPACE_DECL) + decl = decl_namespace (decl); + decl_namespace_list = tree_cons (decl, NULL_TREE, decl_namespace_list); +} + +void +pop_decl_namespace () +{ + decl_namespace_list = TREE_CHAIN (decl_namespace_list); +} + +/* Enter a class or namespace scope. */ + +void +push_scope (t) + tree t; +{ + if (TREE_CODE (t) == NAMESPACE_DECL) + push_decl_namespace (t); + else + pushclass (t, 2); +} + +/* Leave scope pushed by push_scope. */ + +void +pop_scope (t) + tree t; +{ + if (TREE_CODE (t) == NAMESPACE_DECL) + pop_decl_namespace (); + else + popclass (); +} + +/* [basic.lookup.koenig] */ +/* A non-zero return value in the functions below indicates an error. + All nodes allocated in the procedure are on the scratch obstack. */ + +struct arg_lookup +{ + tree name; + tree namespaces; + tree classes; + tree functions; +}; + +static int arg_assoc PROTO((struct arg_lookup*, tree)); +static int arg_assoc_args PROTO((struct arg_lookup*, tree)); +static int arg_assoc_type PROTO((struct arg_lookup*, tree)); +static int add_function PROTO((struct arg_lookup *, tree)); +static int arg_assoc_namespace PROTO((struct arg_lookup *, tree)); +static int arg_assoc_class PROTO((struct arg_lookup *, tree)); + +/* Add a function to the lookup structure. + Returns 1 on error. */ + +static int +add_function (k, fn) + struct arg_lookup *k; + tree fn; +{ + if (ovl_member (fn, k->functions)) + return 0; + /* We must find only functions, or exactly one non-function. */ + if (k->functions && is_overloaded_fn (k->functions) + && is_overloaded_fn (fn)) + k->functions = build_overload (fn, k->functions); + else + if(k->functions) + { + tree f1 = OVL_CURRENT (k->functions); + tree f2 = fn; + if (is_overloaded_fn (f1)) + { + fn = f1; f1 = f2; f2 = fn; + } + cp_error_at ("`%D' is not a function,", f1); + cp_error_at (" conflict with `%D'", f2); + cp_error (" in call to `%D'", k->name); + return 1; + } + else + k->functions = fn; + return 0; +} + +/* Add functions of a namespace to the lookup structure. + Returns 1 on error. */ + +static int +arg_assoc_namespace (k, scope) + struct arg_lookup *k; + tree scope; +{ + tree value; + + if (purpose_member (scope, k->namespaces)) + return 0; + k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces); + + value = namespace_binding (k->name, scope); + if (!value) + return 0; + + for (; value; value = OVL_NEXT (value)) + if (add_function (k, OVL_CURRENT (value))) + return 1; + + return 0; +} + +/* Adds everything associated with class to the lookup structure. + Returns 1 on error. */ + +static int +arg_assoc_class (k, type) + struct arg_lookup* k; + tree type; +{ + tree list, friends, context; + int i; + + if (purpose_member (type, k->classes)) + return 0; + k->classes = tree_cons (type, NULL_TREE, k->classes); + + context = decl_namespace (TYPE_MAIN_DECL (type)); + if (arg_assoc_namespace (k, context)) + return 1; + + /* Process baseclasses. */ + for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++) + if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i))) + return 1; + + /* Process friends. */ + for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list; + list = TREE_CHAIN (list)) + if (k->name == TREE_PURPOSE (list)) + for (friends = TREE_VALUE (list); friends; + friends = TREE_CHAIN (friends)) + /* Only interested in global functions with potentially hidden + (i.e. unqualified) declarations. */ + if (TREE_PURPOSE (list) == error_mark_node && TREE_VALUE (list) + && decl_namespace (TREE_VALUE (list)) == context) + if (add_function (k, TREE_VALUE (list))) + return 1; + + /* Process template arguments. */ + if (CLASSTYPE_TEMPLATE_INFO (type)) + { + list = innermost_args (CLASSTYPE_TI_ARGS (type)); + for (i = 0; i < TREE_VEC_LENGTH (list); ++i) + arg_assoc (k, TREE_VEC_ELT (list, i)); + } + + return 0; +} + +/* Adds everything associated with a given type. + Returns 1 on error. */ + +static int +arg_assoc_type (k, type) + struct arg_lookup *k; + tree type; +{ + switch (TREE_CODE (type)) + { + case VOID_TYPE: + case INTEGER_TYPE: + case REAL_TYPE: + case COMPLEX_TYPE: + case CHAR_TYPE: + case BOOLEAN_TYPE: + return 0; + case RECORD_TYPE: + if (TYPE_PTRMEMFUNC_P (type)) + return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type)); + return arg_assoc_class (k, type); + case POINTER_TYPE: + case REFERENCE_TYPE: + case ARRAY_TYPE: + return arg_assoc_type (k, TREE_TYPE (type)); + case UNION_TYPE: + case ENUMERAL_TYPE: + return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type))); + case OFFSET_TYPE: + /* Pointer to member: associate class type and value type. */ + if (arg_assoc_type (k, TYPE_OFFSET_BASETYPE (type))) + return 1; + return arg_assoc_type (k, TREE_TYPE (type)); + case METHOD_TYPE: + /* The basetype is referenced in the first arg type, so just + fall through. */ + case FUNCTION_TYPE: + /* Associate the parameter types. */ + if (arg_assoc_args (k, TYPE_ARG_TYPES (type))) + return 1; + /* Associate the return type. */ + return arg_assoc_type (k, TREE_TYPE (type)); + case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: + return 0; + case LANG_TYPE: + if (type == unknown_type_node) + return 0; + /* else fall through */ + default: + my_friendly_abort (390); + } + return 0; +} + +/* Adds everything associated with arguments. Returns 1 on error. */ + +static int +arg_assoc_args (k, args) + struct arg_lookup* k; + tree args; +{ + for (; args; args = TREE_CHAIN (args)) + if (arg_assoc (k, TREE_VALUE (args))) + return 1; + return 0; +} + +/* Adds everything associated with a given tree_node. Returns 1 on error. */ + +static int +arg_assoc (k, n) + struct arg_lookup* k; + tree n; +{ + if (n == error_mark_node) + return 0; + + if (TREE_CODE_CLASS (TREE_CODE (n)) == 't') + return arg_assoc_type (k, n); + + if (! type_unknown_p (n)) + return arg_assoc_type (k, TREE_TYPE (n)); + + if (TREE_CODE (n) == ADDR_EXPR) + n = TREE_OPERAND (n, 0); + if (TREE_CODE (n) == COMPONENT_REF) + n = TREE_OPERAND (n, 1); + if (TREE_CODE (n) == OFFSET_REF) + n = TREE_OPERAND (n, 1); + while (TREE_CODE (n) == TREE_LIST) + n = TREE_VALUE (n); + + if (TREE_CODE (n) == FUNCTION_DECL) + return arg_assoc_type (k, TREE_TYPE (n)); + if (TREE_CODE (n) == TEMPLATE_ID_EXPR) + { + /* [basic.lookup.koenig] + + If T is a template-id, its associated namespaces and classes + are the namespace in which the template is defined; for + member templates, the member template's class; the namespaces + and classes associated with the types of the template + arguments provided for template type parameters (excluding + template template parameters); the namespaces in which any + template template arguments are defined; and the classes in + which any member templates used as template template + arguments are defined. [Note: non-type template arguments do + not contribute to the set of associated namespaces. ] */ + tree template = TREE_OPERAND (n, 0); + tree args = TREE_OPERAND (n, 1); + tree ctx; + tree arg; + + /* First, the template. There may actually be more than one if + this is an overloaded function template. But, in that case, + we only need the first; all the functions will be in the same + namespace. */ + template = OVL_CURRENT (template); + + ctx = CP_DECL_CONTEXT (template); + + if (TREE_CODE (ctx) == NAMESPACE_DECL) + { + if (arg_assoc_namespace (k, ctx) == 1) + return 1; + } + /* It must be a member template. */ + else if (arg_assoc_class (k, ctx) == 1) + return 1; + + /* Now the arguments. */ + for (arg = args; arg != NULL_TREE; arg = TREE_CHAIN (arg)) + { + tree t = TREE_VALUE (arg); + + if (TREE_CODE (t) == TEMPLATE_DECL) + { + ctx = CP_DECL_CONTEXT (t); + if (TREE_CODE (ctx) == NAMESPACE_DECL) + { + if (arg_assoc_namespace (k, ctx) == 1) + return 1; + } + else if (arg_assoc_class (k, ctx) == 1) + return 1; + } + else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't' + && arg_assoc_type (k, t) == 1) + return 1; + } + } + else + { + my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715); + + for (; n; n = OVL_CHAIN (n)) + if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n)))) + return 1; + } + + return 0; +} + +/* Performs Koenig lookup depending on arguments, where fns + are the functions found in normal lookup. */ + +tree +lookup_arg_dependent (name, fns, args) + tree name; + tree fns; + tree args; +{ + struct arg_lookup k; + + k.name = name; + k.functions = fns; + k.classes = NULL_TREE; + + /* Note that we've already looked at the current namespace during normal + unqualified lookup, unless we found a decl in function scope. */ + if (fns && ! TREE_PERMANENT (OVL_CURRENT (fns))) + k.namespaces = NULL_TREE; + else + k.namespaces = scratch_tree_cons (current_decl_namespace (), + NULL_TREE, NULL_TREE); + + push_scratch_obstack (); + arg_assoc_args (&k, args); + pop_obstacks (); + return k.functions; +} + +/* Process a namespace-alias declaration. */ + +void +do_namespace_alias (alias, namespace) + tree alias, namespace; +{ + if (TREE_CODE (namespace) != NAMESPACE_DECL) + { + /* The parser did not find it, so it's not there. */ + cp_error ("unknown namespace `%D'", namespace); + return; + } + + namespace = ORIGINAL_NAMESPACE (namespace); + + /* Build the alias. */ + alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node); + DECL_NAMESPACE_ALIAS (alias) = namespace; + pushdecl (alias); +} + +/* Check a non-member using-declaration. Return the name and scope + being used, and the USING_DECL, or NULL_TREE on failure. */ + +static tree +validate_nonmember_using_decl (decl, scope, name) + tree decl; + tree *scope; + tree *name; +{ + if (TREE_CODE (decl) == SCOPE_REF + && TREE_OPERAND (decl, 0) == std_node) + { + if (namespace_bindings_p () + && current_namespace == global_namespace) + /* There's no need for a using declaration at all, here, + since `std' is the same as `::'. We can't just pass this + on because we'll complain later about declaring something + in the same scope as a using declaration with the same + name. We return NULL_TREE which indicates to the caller + that there's no need to do any further processing. */ + return NULL_TREE; + + *scope = global_namespace; + *name = TREE_OPERAND (decl, 1); + } + else if (TREE_CODE (decl) == SCOPE_REF) + { + *scope = TREE_OPERAND (decl, 0); + *name = TREE_OPERAND (decl, 1); + + /* [namespace.udecl] + + A using-declaration for a class member shall be a + member-declaration. */ + if (TREE_CODE (*scope) != NAMESPACE_DECL) + { + if (TYPE_P (*scope)) + cp_error ("`%T' is not a namespace", *scope); + else + cp_error ("`%D' is not a namespace", *scope); + return NULL_TREE; + } + } + else if (TREE_CODE (decl) == IDENTIFIER_NODE + || TREE_CODE (decl) == TYPE_DECL + || TREE_CODE (decl) == TEMPLATE_DECL) + { + *scope = global_namespace; + *name = decl; + } + else + my_friendly_abort (382); + if (TREE_CODE_CLASS (TREE_CODE (*name)) == 'd') + *name = DECL_NAME (*name); + /* Make a USING_DECL. */ + return push_using_decl (*scope, *name); +} + +/* Process local and global using-declarations. */ + +static void +do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype) + tree scope, name; + tree oldval, oldtype; + tree *newval, *newtype; +{ + tree decls; + struct tree_binding _decls; + + *newval = *newtype = NULL_TREE; + decls = binding_init (&_decls); + if (!qualified_lookup_using_namespace (name, scope, decls, 0)) + /* Lookup error */ + return; + + if (!BINDING_VALUE (decls) && !BINDING_TYPE (decls)) + { + cp_error ("`%D' not declared", name); + return; + } + + /* Check for using functions. */ + if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls))) + { + tree tmp, tmp1; + + if (oldval && !is_overloaded_fn (oldval)) + { + duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval); + oldval = NULL_TREE; + } + + *newval = oldval; + for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp)) + { + tree new_fn = OVL_CURRENT (tmp); + + /* [namespace.udecl] + + If a function declaration in namespace scope or block + scope has the same name and the same parameter types as a + function introduced by a using declaration the program is + ill-formed. */ + for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1)) + { + tree old_fn = OVL_CURRENT (tmp1); + + if (!OVL_USED (tmp1) + && compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), + TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) + { + /* There was already a non-using declaration in + this scope with the same parameter types. */ + cp_error ("`%D' is already declared in this scope", + name); + break; + } + else if (duplicate_decls (new_fn, old_fn)) + /* We're re-using something we already used + before. We don't need to add it again. */ + break; + } + + /* If we broke out of the loop, there's no reason to add + this function to the using declarations for this + scope. */ + if (tmp1) + continue; + + *newval = build_overload (OVL_CURRENT (tmp), *newval); + if (TREE_CODE (*newval) != OVERLOAD) + *newval = ovl_cons (*newval, NULL_TREE); + OVL_USED (*newval) = 1; + } + } + else + { + *newval = BINDING_VALUE (decls); + if (oldval) + duplicate_decls (*newval, oldval); + } + + *newtype = BINDING_TYPE (decls); + if (oldtype && *newtype && oldtype != *newtype) + { + cp_error ("using directive `%D' introduced ambiguous type `%T'", + name, oldtype); + return; + } +} + +/* Process a using-declaration not appearing in class or local scope. */ + +void +do_toplevel_using_decl (decl) + tree decl; +{ + tree scope, name, binding; + tree oldval, oldtype, newval, newtype; + + decl = validate_nonmember_using_decl (decl, &scope, &name); + if (decl == NULL_TREE) + return; + + binding = binding_for_name (name, current_namespace); + + oldval = BINDING_VALUE (binding); + oldtype = BINDING_TYPE (binding); + + do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); + + /* Copy declarations found. */ + if (newval) + BINDING_VALUE (binding) = newval; + if (newtype) + BINDING_TYPE (binding) = newtype; + return; +} + +/* Process a using-declaration at function scope. */ + +void +do_local_using_decl (decl) + tree decl; +{ + tree scope, name; + tree oldval, oldtype, newval, newtype; + + decl = validate_nonmember_using_decl (decl, &scope, &name); + if (decl == NULL_TREE) + return; + + oldval = lookup_name_current_level (name); + oldtype = lookup_type_current_level (name); + + do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); + + if (newval) + { + if (is_overloaded_fn (newval)) + { + tree fn, term; + + /* We only need to push declarations for those functions + that were not already bound in the current level. + The old value might be NULL_TREE, it might be a single + function, or an OVERLOAD. */ + if (oldval && TREE_CODE (oldval) == OVERLOAD) + term = OVL_FUNCTION (oldval); + else + term = oldval; + for (fn = newval; fn && OVL_CURRENT (fn) != term; + fn = OVL_NEXT (fn)) + push_overloaded_decl (OVL_CURRENT (fn), + PUSH_LOCAL | PUSH_USING); + } + else + push_local_binding (name, newval, PUSH_USING); + } + if (newtype) + set_identifier_type_value (name, newtype); +} + +tree +do_class_using_decl (decl) + tree decl; +{ + tree name, value; + + if (TREE_CODE (decl) != SCOPE_REF + || TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (decl, 0))) != 't') + { + cp_error ("using-declaration for non-member at class scope"); + return NULL_TREE; + } + name = TREE_OPERAND (decl, 1); + if (TREE_CODE (name) == BIT_NOT_EXPR) + { + cp_error ("using-declaration for destructor"); + return NULL_TREE; + } + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716); + + value = build_lang_field_decl (USING_DECL, name, void_type_node); + DECL_INITIAL (value) = TREE_OPERAND (decl, 0); + return value; +} + +/* Process a using-directive. */ + +void +do_using_directive (namespace) + tree namespace; +{ + if (namespace == std_node) + return; + /* using namespace A::B::C; */ + if (TREE_CODE (namespace) == SCOPE_REF) + namespace = TREE_OPERAND (namespace, 1); + if (TREE_CODE (namespace) == IDENTIFIER_NODE) + { + /* Lookup in lexer did not find a namespace. */ + cp_error ("namespace `%T' undeclared", namespace); + return; + } + if (TREE_CODE (namespace) != NAMESPACE_DECL) + { + cp_error ("`%T' is not a namespace", namespace); + return; + } + namespace = ORIGINAL_NAMESPACE (namespace); + if (!toplevel_bindings_p ()) + push_using_directive (namespace); + else + /* direct usage */ + add_using_namespace (current_namespace, namespace, 0); +} + +void +check_default_args (x) + tree x; +{ + tree arg = TYPE_ARG_TYPES (TREE_TYPE (x)); + int saw_def = 0, i = 0 - (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE); + for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i) + { + if (TREE_PURPOSE (arg)) + saw_def = 1; + else if (saw_def) + { + cp_error_at ("default argument missing for parameter %P of `%+#D'", + i, x); + break; + } + } +} + +void +mark_used (decl) + tree decl; +{ + TREE_USED (decl) = 1; + if (processing_template_decl) + return; + assemble_external (decl); + + /* Is it a synthesized method that needs to be synthesized? */ + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl) + && DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) + /* Kludge: don't synthesize for default args. */ + && current_function_decl) + synthesize_method (decl); + + /* If this is a function or variable that is an instance of some + template, we now know that we will need to actually do the + instantiation. A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO, + if it's a partial instantiation, but there's no need to + instantiate such a thing. We check that DECL is not an explicit + instantiation because that is not checked in instantiate_decl. */ + if (TREE_CODE (decl) != TEMPLATE_DECL + && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) + && !DECL_EXPLICIT_INSTANTIATION (decl)) + instantiate_decl (decl); +} + +/* Helper function for named_class_head_sans_basetype nonterminal. We + have just seen something of the form `AGGR SCOPE::ID'. Return a + TYPE_DECL for the type declared by ID in SCOPE. */ + +tree +handle_class_head (aggr, scope, id) + tree aggr, scope, id; +{ + tree decl; + + if (TREE_CODE (id) == TYPE_DECL) + decl = id; + else if (DECL_CLASS_TEMPLATE_P (id)) + decl = DECL_TEMPLATE_RESULT (id); + else + { + if (scope) + cp_error ("`%T' does not have a nested type named `%D'", scope, id); + else + cp_error ("no file-scope type named `%D'", id); + + decl = TYPE_MAIN_DECL (xref_tag (aggr, make_anon_name (), 1)); + } + + /* This syntax is only allowed when we're defining a type, so we + enter the SCOPE. */ + push_scope (CP_DECL_CONTEXT (decl)); + + /* If we see something like: + + template struct S::I .... + + we must create a TEMPLATE_DECL for the nested type. */ + if (PROCESSING_REAL_TEMPLATE_DECL_P ()) + decl = push_template_decl (decl); + + return decl; +} Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/decl2.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/exception.cc =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/exception.cc (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/exception.cc (revision 60969) @@ -0,0 +1,343 @@ +// Functions for Exception Support for -*- C++ -*- +// Copyright (C) 1994, 95-97, 1998 Free Software Foundation + +// This file is part of GNU CC. + +// GNU CC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. + +// GNU CC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, if you link this library with other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself cause the resulting executable +// to be covered by the GNU General Public License. +// This exception does not however invalidate any other reasons why +// the executable file might be covered by the GNU General Public License. + +#pragma implementation "exception" + +#include "typeinfo" +#include "exception" +#include +#include "gansidecl.h" /* Needed to support macros used in eh-common.h. */ +#include "eh-common.h" + +/* Define terminate, unexpected, set_terminate, set_unexpected as + well as the default terminate func and default unexpected func. */ + +extern std::terminate_handler __terminate_func __attribute__((__noreturn__)); +using std::terminate; + +void +std::terminate () +{ + __terminate_func (); +} + +void +__default_unexpected () +{ + terminate (); +} + +static std::unexpected_handler __unexpected_func __attribute__((__noreturn__)) + = __default_unexpected; + +std::terminate_handler +std::set_terminate (std::terminate_handler func) +{ + std::terminate_handler old = __terminate_func; + + __terminate_func = func; + return old; +} + +std::unexpected_handler +std::set_unexpected (std::unexpected_handler func) +{ + std::unexpected_handler old = __unexpected_func; + + __unexpected_func = func; + return old; +} + +void +std::unexpected () +{ + __unexpected_func (); +} + +/* C++-specific state about the current exception. + This must match init_exception_processing(). + + Note that handlers and caught are not redundant; when rethrown, an + exception can have multiple active handlers and still be considered + uncaught. */ + +struct cp_eh_info +{ + __eh_info eh_info; + void *value; + void *type; + void (*cleanup)(void *, int); + bool caught; + cp_eh_info *next; + long handlers; + void *original_value; +}; + +/* Language-specific EH info pointer, defined in libgcc2. */ + +extern "C" cp_eh_info **__get_eh_info (); // actually void ** + +/* Is P the type_info node for a pointer of some kind? */ + +extern bool __is_pointer (void *); + + +/* OLD Compiler hook to return a pointer to the info for the current exception. + Used by get_eh_info (). This fudges the actualy returned value to + point to the beginning of what USE to be the cp_eh_info structure. + THis is so that old code that dereferences this pointer will find + things where it expects it to be.*/ +extern "C" void * +__cp_exception_info (void) +{ + return &((*__get_eh_info ())->value); +} + +#define CP_EH_INFO ((cp_eh_info *) *__get_eh_info ()) + +/* Old Compiler hook to return a pointer to the info for the current exception. + Used by get_eh_info (). */ + +extern "C" cp_eh_info * +__cp_eh_info (void) +{ + cp_eh_info *p = CP_EH_INFO; + return p; +} + +/* Compiler hook to return a pointer to the info for the current exception, + Set the caught bit, and increment the number of handlers that are + looking at this exception. This makes handlers smaller. */ + +extern "C" cp_eh_info * +__start_cp_handler (void) +{ + cp_eh_info *p = CP_EH_INFO; + p->caught = 1; + p->handlers++; + return p; +} + +/* Allocate a buffer for a cp_eh_info and an exception object of size SIZE, + and return a pointer to the beginning of the object's space. */ + +extern "C" void * malloc (size_t); +extern "C" void * +__eh_alloc (size_t size) +{ + void *p = malloc (size); + if (p == 0) + terminate (); + return p; +} + +/* Free the memory for an cp_eh_info and associated exception, given + a pointer to the cp_eh_info. */ + +extern "C" void free (void *); +extern "C" void +__eh_free (void *p) +{ + free (p); +} + + +typedef void * (* rtimetype) (void); + +extern "C" void * +__cplus_type_matcher (cp_eh_info *info, rtimetype match_info, + exception_descriptor *exception_table) +{ + void *ret; + + /* No exception table implies the old style mechanism, so don't check. */ + if (exception_table != NULL + && exception_table->lang.language != EH_LANG_C_plus_plus) + return NULL; + + if (match_info == CATCH_ALL_TYPE) + return info->value; + + /* we don't worry about version info yet, there is only one version! */ + + void *match_type = match_info (); + ret = __throw_type_match_rtti (match_type, info->type, info->original_value); + /* change value of exception */ + if (ret) + info->value = ret; + return ret; +} + + +/* Compiler hook to push a new exception onto the stack. + Used by expand_throw(). */ + +extern "C" void +__cp_push_exception (void *value, void *type, void (*cleanup)(void *, int)) +{ + cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info)); + + p->value = value; + p->type = type; + p->cleanup = cleanup; + p->handlers = 0; + p->caught = false; + p->original_value = value; + + p->eh_info.match_function = __cplus_type_matcher; + p->eh_info.language = EH_LANG_C_plus_plus; + p->eh_info.version = 1; + + cp_eh_info **q = __get_eh_info (); + + p->next = *q; + *q = p; +} + +/* Compiler hook to pop an exception that has been finalized. Used by + push_eh_cleanup(). P is the info for the exception caught by the + current catch block. */ + +extern "C" void +__cp_pop_exception (cp_eh_info *p) +{ + cp_eh_info **q = __get_eh_info (); + + --p->handlers; + + /* Don't really pop if there are still active handlers for our exception, + or if our exception is being rethrown (i.e. if the active exception is + our exception and it is uncaught). */ + if (p->handlers != 0 + || (p == *q && !p->caught)) + return; + + for (; *q; q = &((*q)->next)) + if (*q == p) + break; + + if (! *q) + terminate (); + + *q = p->next; + + if (p->cleanup) + /* 2 is a magic value for destructors; see build_delete(). */ + p->cleanup (p->original_value, 2); // value may have been adjusted. + + if (! __is_pointer (p->type)) + __eh_free (p->original_value); // value may have been adjusted. + + __eh_free (p); +} + +extern "C" void +__uncatch_exception (void) +{ + cp_eh_info *p = CP_EH_INFO; + if (p == 0) + terminate (); + p->caught = false; +} + +/* As per [except.unexpected]: + If an exception is thrown, we check it against the spec. If it doesn't + match, we call unexpected (). If unexpected () throws, we check that + exception against the spec. If it doesn't match, if the spec allows + bad_exception we throw that; otherwise we call terminate (). + + The compiler treats an exception spec as a try block with a generic + handler that just calls this function with a list of the allowed + exception types, so we have an active exception that can be rethrown. + + This function does not return. */ + +extern "C" void +__check_eh_spec (int n, const void **spec) +{ + cp_eh_info *p = CP_EH_INFO; + + for (int i = 0; i < n; ++i) + { + if (__throw_type_match_rtti (spec[i], p->type, p->value)) + throw; + } + + try + { + std::unexpected (); + } + catch (...) + { + // __exception_info is an artificial var pushed into each catch block. + if (p != __exception_info) + { + p = __exception_info; + for (int i = 0; i < n; ++i) + { + if (__throw_type_match_rtti (spec[i], p->type, p->value)) + throw; + } + } + + const std::type_info &bad_exc = typeid (std::bad_exception); + for (int i = 0; i < n; ++i) + { + if (__throw_type_match_rtti (spec[i], &bad_exc, p->value)) + throw std::bad_exception (); + } + + terminate (); + } +} + +extern "C" void +__throw_bad_cast (void) +{ + throw std::bad_cast (); +} + +extern "C" void +__throw_bad_typeid (void) +{ + throw std::bad_typeid (); +} + +/* Has the current exception been caught? */ + +bool +std::uncaught_exception () +{ + cp_eh_info *p = CP_EH_INFO; + return p && ! p->caught; +} + +const char * std::exception:: +what () const +{ + return typeid (*this).name (); +} Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/exception.cc ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/gxxint.texi =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/gxxint.texi (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/gxxint.texi (revision 60969) @@ -0,0 +1,2075 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename g++int.info +@settitle G++ internals +@setchapternewpage odd +@c %**end of header + +@node Top, Limitations of g++, (dir), (dir) +@chapter Internal Architecture of the Compiler + +This is meant to describe the C++ front-end for gcc in detail. +Questions and comments to Benjamin Kosnik @code{}. + +@menu +* Limitations of g++:: +* Routines:: +* Implementation Specifics:: +* Glossary:: +* Macros:: +* Typical Behavior:: +* Coding Conventions:: +* Templates:: +* Access Control:: +* Error Reporting:: +* Parser:: +* Exception Handling:: +* Free Store:: +* Mangling:: Function name mangling for C++ and Java +* Vtables:: Two ways to do virtual functions +* Concept Index:: +@end menu + +@node Limitations of g++, Routines, Top, Top +@section Limitations of g++ + +@itemize @bullet +@item +Limitations on input source code: 240 nesting levels with the parser +stacksize (YYSTACKSIZE) set to 500 (the default), and requires around +16.4k swap space per nesting level. The parser needs about 2.09 * +number of nesting levels worth of stackspace. + +@cindex pushdecl_class_level +@item +I suspect there are other uses of pushdecl_class_level that do not call +set_identifier_type_value in tandem with the call to +pushdecl_class_level. It would seem to be an omission. + +@cindex access checking +@item +Access checking is unimplemented for nested types. + +@cindex @code{volatile} +@item +@code{volatile} is not implemented in general. + +@end itemize + +@node Routines, Implementation Specifics, Limitations of g++, Top +@section Routines + +This section describes some of the routines used in the C++ front-end. + +@code{build_vtable} and @code{prepare_fresh_vtable} is used only within +the @file{cp-class.c} file, and only in @code{finish_struct} and +@code{modify_vtable_entries}. + +@code{build_vtable}, @code{prepare_fresh_vtable}, and +@code{finish_struct} are the only routines that set @code{DECL_VPARENT}. + +@code{finish_struct} can steal the virtual function table from parents, +this prohibits related_vslot from working. When finish_struct steals, +we know that + +@example +get_binfo (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (t)), t, 0) +@end example + +@noindent +will get the related binfo. + +@code{layout_basetypes} does something with the VIRTUALS. + +Supposedly (according to Tiemann) most of the breadth first searching +done, like in @code{get_base_distance} and in @code{get_binfo} was not +because of any design decision. I have since found out the at least one +part of the compiler needs the notion of depth first binfo searching, I +am going to try and convert the whole thing, it should just work. The +term left-most refers to the depth first left-most node. It uses +@code{MAIN_VARIANT == type} as the condition to get left-most, because +the things that have @code{BINFO_OFFSET}s of zero are shared and will +have themselves as their own @code{MAIN_VARIANT}s. The non-shared right +ones, are copies of the left-most one, hence if it is its own +@code{MAIN_VARIANT}, we know it IS a left-most one, if it is not, it is +a non-left-most one. + +@code{get_base_distance}'s path and distance matters in its use in: + +@itemize @bullet +@item +@code{prepare_fresh_vtable} (the code is probably wrong) +@item +@code{init_vfields} Depends upon distance probably in a safe way, +build_offset_ref might use partial paths to do further lookups, +hack_identifier is probably not properly checking access. + +@item +@code{get_first_matching_virtual} probably should check for +@code{get_base_distance} returning -2. + +@item +@code{resolve_offset_ref} should be called in a more deterministic +manner. Right now, it is called in some random contexts, like for +arguments at @code{build_method_call} time, @code{default_conversion} +time, @code{convert_arguments} time, @code{build_unary_op} time, +@code{build_c_cast} time, @code{build_modify_expr} time, +@code{convert_for_assignment} time, and +@code{convert_for_initialization} time. + +But, there are still more contexts it needs to be called in, one was the +ever simple: + +@example +if (obj.*pmi != 7) + @dots{} +@end example + +Seems that the problems were due to the fact that @code{TREE_TYPE} of +the @code{OFFSET_REF} was not a @code{OFFSET_TYPE}, but rather the type +of the referent (like @code{INTEGER_TYPE}). This problem was fixed by +changing @code{default_conversion} to check @code{TREE_CODE (x)}, +instead of only checking @code{TREE_CODE (TREE_TYPE (x))} to see if it +was @code{OFFSET_TYPE}. + +@end itemize + +@node Implementation Specifics, Glossary, Routines, Top +@section Implementation Specifics + +@itemize @bullet +@item Explicit Initialization + +The global list @code{current_member_init_list} contains the list of +mem-initializers specified in a constructor declaration. For example: + +@example +foo::foo() : a(1), b(2) @{@} +@end example + +@noindent +will initialize @samp{a} with 1 and @samp{b} with 2. +@code{expand_member_init} places each initialization (a with 1) on the +global list. Then, when the fndecl is being processed, +@code{emit_base_init} runs down the list, initializing them. It used to +be the case that g++ first ran down @code{current_member_init_list}, +then ran down the list of members initializing the ones that weren't +explicitly initialized. Things were rewritten to perform the +initializations in order of declaration in the class. So, for the above +example, @samp{a} and @samp{b} will be initialized in the order that +they were declared: + +@example +class foo @{ public: int b; int a; foo (); @}; +@end example + +@noindent +Thus, @samp{b} will be initialized with 2 first, then @samp{a} will be +initialized with 1, regardless of how they're listed in the mem-initializer. + +@item The Explicit Keyword + +The use of @code{explicit} on a constructor is used by @code{grokdeclarator} +to set the field @code{DECL_NONCONVERTING_P}. That value is used by +@code{build_method_call} and @code{build_user_type_conversion_1} to decide +if a particular constructor should be used as a candidate for conversions. + +@end itemize + +@node Glossary, Macros, Implementation Specifics, Top +@section Glossary + +@table @r +@item binfo +The main data structure in the compiler used to represent the +inheritance relationships between classes. The data in the binfo can be +accessed by the BINFO_ accessor macros. + +@item vtable +@itemx virtual function table + +The virtual function table holds information used in virtual function +dispatching. In the compiler, they are usually referred to as vtables, +or vtbls. The first index is not used in the normal way, I believe it +is probably used for the virtual destructor. There are two forms of +virtual tables, one that has offsets in addition to pointers, and one +using thunks. @xref{Vtables}. + +@item vfield + +vfields can be thought of as the base information needed to build +vtables. For every vtable that exists for a class, there is a vfield. +See also vtable and virtual function table pointer. When a type is used +as a base class to another type, the virtual function table for the +derived class can be based upon the vtable for the base class, just +extended to include the additional virtual methods declared in the +derived class. The virtual function table from a virtual base class is +never reused in a derived class. @code{is_normal} depends upon this. + +@item virtual function table pointer + +These are @code{FIELD_DECL}s that are pointer types that point to +vtables. See also vtable and vfield. +@end table + +@node Macros, Typical Behavior, Glossary, Top +@section Macros + +This section describes some of the macros used on trees. The list +should be alphabetical. Eventually all macros should be documented +here. + +@table @code +@item BINFO_BASETYPES +A vector of additional binfos for the types inherited by this basetype. +The binfos are fully unshared (except for virtual bases, in which +case the binfo structure is shared). + + If this basetype describes type D as inherited in C, + and if the basetypes of D are E anf F, + then this vector contains binfos for inheritance of E and F by C. + +Has values of: + + TREE_VECs + + +@item BINFO_INHERITANCE_CHAIN +Temporarily used to represent specific inheritances. It usually points +to the binfo associated with the lesser derived type, but it can be +reversed by reverse_path. For example: + +@example + Z ZbY least derived + | + Y YbX + | + X Xb most derived + +TYPE_BINFO (X) == Xb +BINFO_INHERITANCE_CHAIN (Xb) == YbX +BINFO_INHERITANCE_CHAIN (Yb) == ZbY +BINFO_INHERITANCE_CHAIN (Zb) == 0 +@end example + +Not sure is the above is really true, get_base_distance has is point +towards the most derived type, opposite from above. + +Set by build_vbase_path, recursive_bounded_basetype_p, +get_base_distance, lookup_field, lookup_fnfields, and reverse_path. + +What things can this be used on: + + TREE_VECs that are binfos + + +@item BINFO_OFFSET +The offset where this basetype appears in its containing type. +BINFO_OFFSET slot holds the offset (in bytes) from the base of the +complete object to the base of the part of the object that is allocated +on behalf of this `type'. This is always 0 except when there is +multiple inheritance. + +Used on TREE_VEC_ELTs of the binfos BINFO_BASETYPES (...) for example. + + +@item BINFO_VIRTUALS +A unique list of functions for the virtual function table. See also +TYPE_BINFO_VIRTUALS. + +What things can this be used on: + + TREE_VECs that are binfos + + +@item BINFO_VTABLE +Used to find the VAR_DECL that is the virtual function table associated +with this binfo. See also TYPE_BINFO_VTABLE. To get the virtual +function table pointer, see CLASSTYPE_VFIELD. + +What things can this be used on: + + TREE_VECs that are binfos + +Has values of: + + VAR_DECLs that are virtual function tables + + +@item BLOCK_SUPERCONTEXT +In the outermost scope of each function, it points to the FUNCTION_DECL +node. It aids in better DWARF support of inline functions. + + +@item CLASSTYPE_TAGS +CLASSTYPE_TAGS is a linked (via TREE_CHAIN) list of member classes of a +class. TREE_PURPOSE is the name, TREE_VALUE is the type (pushclass scans +these and calls pushtag on them.) + +finish_struct scans these to produce TYPE_DECLs to add to the +TYPE_FIELDS of the type. + +It is expected that name found in the TREE_PURPOSE slot is unique, +resolve_scope_to_name is one such place that depends upon this +uniqueness. + + +@item CLASSTYPE_METHOD_VEC +The following is true after finish_struct has been called (on the +class?) but not before. Before finish_struct is called, things are +different to some extent. Contains a TREE_VEC of methods of the class. +The TREE_VEC_LENGTH is the number of differently named methods plus one +for the 0th entry. The 0th entry is always allocated, and reserved for +ctors and dtors. If there are none, TREE_VEC_ELT(N,0) == NULL_TREE. +Each entry of the TREE_VEC is a FUNCTION_DECL. For each FUNCTION_DECL, +there is a DECL_CHAIN slot. If the FUNCTION_DECL is the last one with a +given name, the DECL_CHAIN slot is NULL_TREE. Otherwise it is the next +method that has the same name (but a different signature). It would +seem that it is not true that because the DECL_CHAIN slot is used in +this way, we cannot call pushdecl to put the method in the global scope +(cause that would overwrite the TREE_CHAIN slot), because they use +different _CHAINs. finish_struct_methods setups up one version of the +TREE_CHAIN slots on the FUNCTION_DECLs. + +friends are kept in TREE_LISTs, so that there's no need to use their +TREE_CHAIN slot for anything. + +Has values of: + + TREE_VECs + + +@item CLASSTYPE_VFIELD +Seems to be in the process of being renamed TYPE_VFIELD. Use on types +to get the main virtual function table pointer. To get the virtual +function table use BINFO_VTABLE (TYPE_BINFO ()). + +Has values of: + + FIELD_DECLs that are virtual function table pointers + +What things can this be used on: + + RECORD_TYPEs + + +@item DECL_CLASS_CONTEXT +Identifies the context that the _DECL was found in. For virtual function +tables, it points to the type associated with the virtual function +table. See also DECL_CONTEXT, DECL_FIELD_CONTEXT and DECL_FCONTEXT. + +The difference between this and DECL_CONTEXT, is that for virtuals +functions like: + +@example +struct A +@{ + virtual int f (); +@}; + +struct B : A +@{ + int f (); +@}; + +DECL_CONTEXT (A::f) == A +DECL_CLASS_CONTEXT (A::f) == A + +DECL_CONTEXT (B::f) == A +DECL_CLASS_CONTEXT (B::f) == B +@end example + +Has values of: + + RECORD_TYPEs, or UNION_TYPEs + +What things can this be used on: + + TYPE_DECLs, _DECLs + + +@item DECL_CONTEXT +Identifies the context that the _DECL was found in. Can be used on +virtual function tables to find the type associated with the virtual +function table, but since they are FIELD_DECLs, DECL_FIELD_CONTEXT is a +better access method. Internally the same as DECL_FIELD_CONTEXT, so +don't us both. See also DECL_FIELD_CONTEXT, DECL_FCONTEXT and +DECL_CLASS_CONTEXT. + +Has values of: + + RECORD_TYPEs + + +What things can this be used on: + +@display +VAR_DECLs that are virtual function tables +_DECLs +@end display + + +@item DECL_FIELD_CONTEXT +Identifies the context that the FIELD_DECL was found in. Internally the +same as DECL_CONTEXT, so don't us both. See also DECL_CONTEXT, +DECL_FCONTEXT and DECL_CLASS_CONTEXT. + +Has values of: + + RECORD_TYPEs + +What things can this be used on: + +@display +FIELD_DECLs that are virtual function pointers +FIELD_DECLs +@end display + + +@item DECL_NAME + +Has values of: + +@display +0 for things that don't have names +IDENTIFIER_NODEs for TYPE_DECLs +@end display + +@item DECL_IGNORED_P +A bit that can be set to inform the debug information output routines in +the back-end that a certain _DECL node should be totally ignored. + +Used in cases where it is known that the debugging information will be +output in another file, or where a sub-type is known not to be needed +because the enclosing type is not needed. + +A compiler constructed virtual destructor in derived classes that do not +define an explicit destructor that was defined explicit in a base class +has this bit set as well. Also used on __FUNCTION__ and +__PRETTY_FUNCTION__ to mark they are ``compiler generated.'' c-decl and +c-lex.c both want DECL_IGNORED_P set for ``internally generated vars,'' +and ``user-invisible variable.'' + +Functions built by the C++ front-end such as default destructors, +virtual destructors and default constructors want to be marked that +they are compiler generated, but unsure why. + +Currently, it is used in an absolute way in the C++ front-end, as an +optimization, to tell the debug information output routines to not +generate debugging information that will be output by another separately +compiled file. + + +@item DECL_VIRTUAL_P +A flag used on FIELD_DECLs and VAR_DECLs. (Documentation in tree.h is +wrong.) Used in VAR_DECLs to indicate that the variable is a vtable. +It is also used in FIELD_DECLs for vtable pointers. + +What things can this be used on: + + FIELD_DECLs and VAR_DECLs + + +@item DECL_VPARENT +Used to point to the parent type of the vtable if there is one, else it +is just the type associated with the vtable. Because of the sharing of +virtual function tables that goes on, this slot is not very useful, and +is in fact, not used in the compiler at all. It can be removed. + +What things can this be used on: + + VAR_DECLs that are virtual function tables + +Has values of: + + RECORD_TYPEs maybe UNION_TYPEs + + +@item DECL_FCONTEXT +Used to find the first baseclass in which this FIELD_DECL is defined. +See also DECL_CONTEXT, DECL_FIELD_CONTEXT and DECL_CLASS_CONTEXT. + +How it is used: + + Used when writing out debugging information about vfield and + vbase decls. + +What things can this be used on: + + FIELD_DECLs that are virtual function pointers + FIELD_DECLs + + +@item DECL_REFERENCE_SLOT +Used to hold the initialize for the reference. + +What things can this be used on: + + PARM_DECLs and VAR_DECLs that have a reference type + + +@item DECL_VINDEX +Used for FUNCTION_DECLs in two different ways. Before the structure +containing the FUNCTION_DECL is laid out, DECL_VINDEX may point to a +FUNCTION_DECL in a base class which is the FUNCTION_DECL which this +FUNCTION_DECL will replace as a virtual function. When the class is +laid out, this pointer is changed to an INTEGER_CST node which is +suitable to find an index into the virtual function table. See +get_vtable_entry as to how one can find the right index into the virtual +function table. The first index 0, of a virtual function table it not +used in the normal way, so the first real index is 1. + +DECL_VINDEX may be a TREE_LIST, that would seem to be a list of +overridden FUNCTION_DECLs. add_virtual_function has code to deal with +this when it uses the variable base_fndecl_list, but it would seem that +somehow, it is possible for the TREE_LIST to pursist until method_call, +and it should not. + + +What things can this be used on: + + FUNCTION_DECLs + + +@item DECL_SOURCE_FILE +Identifies what source file a particular declaration was found in. + +Has values of: + + "" on TYPE_DECLs to mean the typedef is built in + + +@item DECL_SOURCE_LINE +Identifies what source line number in the source file the declaration +was found at. + +Has values of: + +@display +0 for an undefined label + +0 for TYPE_DECLs that are internally generated + +0 for FUNCTION_DECLs for functions generated by the compiler + (not yet, but should be) + +0 for ``magic'' arguments to functions, that the user has no + control over +@end display + + +@item TREE_USED + +Has values of: + + 0 for unused labels + + +@item TREE_ADDRESSABLE +A flag that is set for any type that has a constructor. + + +@item TREE_COMPLEXITY +They seem a kludge way to track recursion, poping, and pushing. They only +appear in cp-decl.c and cp-decl2.c, so the are a good candidate for +proper fixing, and removal. + + +@item TREE_HAS_CONSTRUCTOR +A flag to indicate when a CALL_EXPR represents a call to a constructor. +If set, we know that the type of the object, is the complete type of the +object, and that the value returned is nonnull. When used in this +fashion, it is an optimization. Can also be used on SAVE_EXPRs to +indicate when they are of fixed type and nonnull. Can also be used on +INDIRECT_EXPRs on CALL_EXPRs that represent a call to a constructor. + + +@item TREE_PRIVATE +Set for FIELD_DECLs by finish_struct. But not uniformly set. + +The following routines do something with PRIVATE access: +build_method_call, alter_access, finish_struct_methods, +finish_struct, convert_to_aggr, CWriteLanguageDecl, CWriteLanguageType, +CWriteUseObject, compute_access, lookup_field, dfs_pushdecl, +GNU_xref_member, dbxout_type_fields, dbxout_type_method_1 + + +@item TREE_PROTECTED +The following routines do something with PROTECTED access: +build_method_call, alter_access, finish_struct, convert_to_aggr, +CWriteLanguageDecl, CWriteLanguageType, CWriteUseObject, +compute_access, lookup_field, GNU_xref_member, dbxout_type_fields, +dbxout_type_method_1 + + +@item TYPE_BINFO +Used to get the binfo for the type. + +Has values of: + + TREE_VECs that are binfos + +What things can this be used on: + + RECORD_TYPEs + + +@item TYPE_BINFO_BASETYPES +See also BINFO_BASETYPES. + +@item TYPE_BINFO_VIRTUALS +A unique list of functions for the virtual function table. See also +BINFO_VIRTUALS. + +What things can this be used on: + + RECORD_TYPEs + + +@item TYPE_BINFO_VTABLE +Points to the virtual function table associated with the given type. +See also BINFO_VTABLE. + +What things can this be used on: + + RECORD_TYPEs + +Has values of: + + VAR_DECLs that are virtual function tables + + +@item TYPE_NAME +Names the type. + +Has values of: + +@display +0 for things that don't have names. +should be IDENTIFIER_NODE for RECORD_TYPEs UNION_TYPEs and + ENUM_TYPEs. +TYPE_DECL for RECORD_TYPEs, UNION_TYPEs and ENUM_TYPEs, but + shouldn't be. +TYPE_DECL for typedefs, unsure why. +@end display + +What things can one use this on: + +@display +TYPE_DECLs +RECORD_TYPEs +UNION_TYPEs +ENUM_TYPEs +@end display + +History: + + It currently points to the TYPE_DECL for RECORD_TYPEs, + UNION_TYPEs and ENUM_TYPEs, but it should be history soon. + + +@item TYPE_METHODS +Synonym for @code{CLASSTYPE_METHOD_VEC}. Chained together with +@code{TREE_CHAIN}. @file{dbxout.c} uses this to get at the methods of a +class. + + +@item TYPE_DECL +Used to represent typedefs, and used to represent bindings layers. + +Components: + + DECL_NAME is the name of the typedef. For example, foo would + be found in the DECL_NAME slot when @code{typedef int foo;} is + seen. + + DECL_SOURCE_LINE identifies what source line number in the + source file the declaration was found at. A value of 0 + indicates that this TYPE_DECL is just an internal binding layer + marker, and does not correspond to a user supplied typedef. + + DECL_SOURCE_FILE + +@item TYPE_FIELDS +A linked list (via @code{TREE_CHAIN}) of member types of a class. The +list can contain @code{TYPE_DECL}s, but there can also be other things +in the list apparently. See also @code{CLASSTYPE_TAGS}. + + +@item TYPE_VIRTUAL_P +A flag used on a @code{FIELD_DECL} or a @code{VAR_DECL}, indicates it is +a virtual function table or a pointer to one. When used on a +@code{FUNCTION_DECL}, indicates that it is a virtual function. When +used on an @code{IDENTIFIER_NODE}, indicates that a function with this +same name exists and has been declared virtual. + +When used on types, it indicates that the type has virtual functions, or +is derived from one that does. + +Not sure if the above about virtual function tables is still true. See +also info on @code{DECL_VIRTUAL_P}. + +What things can this be used on: + + FIELD_DECLs, VAR_DECLs, FUNCTION_DECLs, IDENTIFIER_NODEs + + +@item VF_BASETYPE_VALUE +Get the associated type from the binfo that caused the given vfield to +exist. This is the least derived class (the most parent class) that +needed a virtual function table. It is probably the case that all uses +of this field are misguided, but they need to be examined on a +case-by-case basis. See history for more information on why the +previous statement was made. + +Set at @code{finish_base_struct} time. + +What things can this be used on: + + TREE_LISTs that are vfields + +History: + + This field was used to determine if a virtual function table's + slot should be filled in with a certain virtual function, by + checking to see if the type returned by VF_BASETYPE_VALUE was a + parent of the context in which the old virtual function existed. + This incorrectly assumes that a given type _could_ not appear as + a parent twice in a given inheritance lattice. For single + inheritance, this would in fact work, because a type could not + possibly appear more than once in an inheritance lattice, but + with multiple inheritance, a type can appear more than once. + + +@item VF_BINFO_VALUE +Identifies the binfo that caused this vfield to exist. If this vfield +is from the first direct base class that has a virtual function table, +then VF_BINFO_VALUE is NULL_TREE, otherwise it will be the binfo of the +direct base where the vfield came from. Can use @code{TREE_VIA_VIRTUAL} +on result to find out if it is a virtual base class. Related to the +binfo found by + +@example +get_binfo (VF_BASETYPE_VALUE (vfield), t, 0) +@end example + +@noindent +where @samp{t} is the type that has the given vfield. + +@example +get_binfo (VF_BASETYPE_VALUE (vfield), t, 0) +@end example + +@noindent +will return the binfo for the given vfield. + +May or may not be set at @code{modify_vtable_entries} time. Set at +@code{finish_base_struct} time. + +What things can this be used on: + + TREE_LISTs that are vfields + + +@item VF_DERIVED_VALUE +Identifies the type of the most derived class of the vfield, excluding +the class this vfield is for. + +Set at @code{finish_base_struct} time. + +What things can this be used on: + + TREE_LISTs that are vfields + + +@item VF_NORMAL_VALUE +Identifies the type of the most derived class of the vfield, including +the class this vfield is for. + +Set at @code{finish_base_struct} time. + +What things can this be used on: + + TREE_LISTs that are vfields + + +@item WRITABLE_VTABLES +This is a option that can be defined when building the compiler, that +will cause the compiler to output vtables into the data segment so that +the vtables maybe written. This is undefined by default, because +normally the vtables should be unwritable. People that implement object +I/O facilities may, or people that want to change the dynamic type of +objects may want to have the vtables writable. Another way of achieving +this would be to make a copy of the vtable into writable memory, but the +drawback there is that that method only changes the type for one object. + +@end table + +@node Typical Behavior, Coding Conventions, Macros, Top +@section Typical Behavior + +@cindex parse errors + +Whenever seemingly normal code fails with errors like +@code{syntax error at `\@{'}, it's highly likely that grokdeclarator is +returning a NULL_TREE for whatever reason. + +@node Coding Conventions, Templates, Typical Behavior, Top +@section Coding Conventions + +It should never be that case that trees are modified in-place by the +back-end, @emph{unless} it is guaranteed that the semantics are the same +no matter how shared the tree structure is. @file{fold-const.c} still +has some cases where this is not true, but rms hypothesizes that this +will never be a problem. + +@node Templates, Access Control, Coding Conventions, Top +@section Templates + +A template is represented by a @code{TEMPLATE_DECL}. The specific +fields used are: + +@table @code +@item DECL_TEMPLATE_RESULT +The generic decl on which instantiations are based. This looks just +like any other decl. + +@item DECL_TEMPLATE_PARMS +The parameters to this template. +@end table + +The generic decl is parsed as much like any other decl as possible, +given the parameterization. The template decl is not built up until the +generic decl has been completed. For template classes, a template decl +is generated for each member function and static data member, as well. + +Template members of template classes are represented by a TEMPLATE_DECL +for the class' parameters around another TEMPLATE_DECL for the member's +parameters. + +All declarations that are instantiations or specializations of templates +refer to their template and parameters through DECL_TEMPLATE_INFO. + +How should I handle parsing member functions with the proper param +decls? Set them up again or try to use the same ones? Currently we do +the former. We can probably do this without any extra machinery in +store_pending_inline, by deducing the parameters from the decl in +do_pending_inlines. PRE_PARSED_TEMPLATE_DECL? + +If a base is a parm, we can't check anything about it. If a base is not +a parm, we need to check it for name binding. Do finish_base_struct if +no bases are parameterized (only if none, including indirect, are +parms). Nah, don't bother trying to do any of this until instantiation +-- we only need to do name binding in advance. + +Always set up method vec and fields, inc. synthesized methods. Really? +We can't know the types of the copy folks, or whether we need a +destructor, or can have a default ctor, until we know our bases and +fields. Otherwise, we can assume and fix ourselves later. Hopefully. + +@node Access Control, Error Reporting, Templates, Top +@section Access Control +The function compute_access returns one of three values: + +@table @code +@item access_public +means that the field can be accessed by the current lexical scope. + +@item access_protected +means that the field cannot be accessed by the current lexical scope +because it is protected. + +@item access_private +means that the field cannot be accessed by the current lexical scope +because it is private. +@end table + +DECL_ACCESS is used for access declarations; alter_access creates a list +of types and accesses for a given decl. + +Formerly, DECL_@{PUBLIC,PROTECTED,PRIVATE@} corresponded to the return +codes of compute_access and were used as a cache for compute_access. +Now they are not used at all. + +TREE_PROTECTED and TREE_PRIVATE are used to record the access levels +granted by the containing class. BEWARE: TREE_PUBLIC means something +completely unrelated to access control! + +@node Error Reporting, Parser, Access Control, Top +@section Error Reporting + +The C++ front-end uses a call-back mechanism to allow functions to print +out reasonable strings for types and functions without putting extra +logic in the functions where errors are found. The interface is through +the @code{cp_error} function (or @code{cp_warning}, etc.). The +syntax is exactly like that of @code{error}, except that a few more +conversions are supported: + +@itemize @bullet +@item +%C indicates a value of `enum tree_code'. +@item +%D indicates a *_DECL node. +@item +%E indicates a *_EXPR node. +@item +%L indicates a value of `enum languages'. +@item +%P indicates the name of a parameter (i.e. "this", "1", "2", ...) +@item +%T indicates a *_TYPE node. +@item +%O indicates the name of an operator (MODIFY_EXPR -> "operator ="). + +@end itemize + +There is some overlap between these; for instance, any of the node +options can be used for printing an identifier (though only @code{%D} +tries to decipher function names). + +For a more verbose message (@code{class foo} as opposed to just @code{foo}, +including the return type for functions), use @code{%#c}. +To have the line number on the error message indicate the line of the +DECL, use @code{cp_error_at} and its ilk; to indicate which argument you want, +use @code{%+D}, or it will default to the first. + +@node Parser, Exception Handling, Error Reporting, Top +@section Parser + +Some comments on the parser: + +The @code{after_type_declarator} / @code{notype_declarator} hack is +necessary in order to allow redeclarations of @code{TYPENAME}s, for +instance + +@example +typedef int foo; +class A @{ + char *foo; +@}; +@end example + +In the above, the first @code{foo} is parsed as a @code{notype_declarator}, +and the second as a @code{after_type_declarator}. + +Ambiguities: + +There are currently four reduce/reduce ambiguities in the parser. They are: + +1) Between @code{template_parm} and +@code{named_class_head_sans_basetype}, for the tokens @code{aggr +identifier}. This situation occurs in code looking like + +@example +template class A @{ @}; +@end example + +It is ambiguous whether @code{class T} should be parsed as the +declaration of a template type parameter named @code{T} or an unnamed +constant parameter of type @code{class T}. Section 14.6, paragraph 3 of +the January '94 working paper states that the first interpretation is +the correct one. This ambiguity results in two reduce/reduce conflicts. + +2) Between @code{primary} and @code{type_id} for code like @samp{int()} +in places where both can be accepted, such as the argument to +@code{sizeof}. Section 8.1 of the pre-San Diego working paper specifies +that these ambiguous constructs will be interpreted as @code{typename}s. +This ambiguity results in six reduce/reduce conflicts between +@samp{absdcl} and @samp{functional_cast}. + +3) Between @code{functional_cast} and +@code{complex_direct_notype_declarator}, for various token strings. +This situation occurs in code looking like + +@example +int (*a); +@end example + +This code is ambiguous; it could be a declaration of the variable +@samp{a} as a pointer to @samp{int}, or it could be a functional cast of +@samp{*a} to @samp{int}. Section 6.8 specifies that the former +interpretation is correct. This ambiguity results in 7 reduce/reduce +conflicts. Another aspect of this ambiguity is code like 'int (x[2]);', +which is resolved at the '[' and accounts for 6 reduce/reduce conflicts +between @samp{direct_notype_declarator} and +@samp{primary}/@samp{overqualified_id}. Finally, there are 4 r/r +conflicts between @samp{expr_or_declarator} and @samp{primary} over code +like 'int (a);', which could probably be resolved but would also +probably be more trouble than it's worth. In all, this situation +accounts for 17 conflicts. Ack! + +The second case above is responsible for the failure to parse 'LinppFile +ppfile (String (argv[1]), &outs, argc, argv);' (from Rogue Wave +Math.h++) as an object declaration, and must be fixed so that it does +not resolve until later. + +4) Indirectly between @code{after_type_declarator} and @code{parm}, for +type names. This occurs in (as one example) code like + +@example +typedef int foo, bar; +class A @{ + foo (bar); +@}; +@end example + +What is @code{bar} inside the class definition? We currently interpret +it as a @code{parm}, as does Cfront, but IBM xlC interprets it as an +@code{after_type_declarator}. I believe that xlC is correct, in light +of 7.1p2, which says "The longest sequence of @i{decl-specifiers} that +could possibly be a type name is taken as the @i{decl-specifier-seq} of +a @i{declaration}." However, it seems clear that this rule must be +violated in the case of constructors. This ambiguity accounts for 8 +conflicts. + +Unlike the others, this ambiguity is not recognized by the Working Paper. + +@node Exception Handling, Free Store, Parser, Top +@section Exception Handling + +Note, exception handling in g++ is still under development. + +This section describes the mapping of C++ exceptions in the C++ +front-end, into the back-end exception handling framework. + +The basic mechanism of exception handling in the back-end is +unwind-protect a la elisp. This is a general, robust, and language +independent representation for exceptions. + +The C++ front-end exceptions are mapping into the unwind-protect +semantics by the C++ front-end. The mapping is describe below. + +When -frtti is used, rtti is used to do exception object type checking, +when it isn't used, the encoded name for the type of the object being +thrown is used instead. All code that originates exceptions, even code +that throws exceptions as a side effect, like dynamic casting, and all +code that catches exceptions must be compiled with either -frtti, or +-fno-rtti. It is not possible to mix rtti base exception handling +objects with code that doesn't use rtti. The exceptions to this, are +code that doesn't catch or throw exceptions, catch (...), and code that +just rethrows an exception. + +Currently we use the normal mangling used in building functions names +(int's are "i", const char * is PCc) to build the non-rtti base type +descriptors for exception handling. These descriptors are just plain +NULL terminated strings, and internally they are passed around as char +*. + +In C++, all cleanups should be protected by exception regions. The +region starts just after the reason why the cleanup is created has +ended. For example, with an automatic variable, that has a constructor, +it would be right after the constructor is run. The region ends just +before the finalization is expanded. Since the backend may expand the +cleanup multiple times along different paths, once for normal end of the +region, once for non-local gotos, once for returns, etc, the backend +must take special care to protect the finalization expansion, if the +expansion is for any other reason than normal region end, and it is +`inline' (it is inside the exception region). The backend can either +choose to move them out of line, or it can created an exception region +over the finalization to protect it, and in the handler associated with +it, it would not run the finalization as it otherwise would have, but +rather just rethrow to the outer handler, careful to skip the normal +handler for the original region. + +In Ada, they will use the more runtime intensive approach of having +fewer regions, but at the cost of additional work at run time, to keep a +list of things that need cleanups. When a variable has finished +construction, they add the cleanup to the list, when the come to the end +of the lifetime of the variable, the run the list down. If the take a +hit before the section finishes normally, they examine the list for +actions to perform. I hope they add this logic into the back-end, as it +would be nice to get that alternative approach in C++. + +On an rs6000, xlC stores exception objects on that stack, under the try +block. When is unwinds down into a handler, the frame pointer is +adjusted back to the normal value for the frame in which the handler +resides, and the stack pointer is left unchanged from the time at which +the object was thrown. This is so that there is always someplace for +the exception object, and nothing can overwrite it, once we start +throwing. The only bad part, is that the stack remains large. + +The below points out some things that work in g++'s exception handling. + +All completely constructed temps and local variables are cleaned up in +all unwinded scopes. Completely constructed parts of partially +constructed objects are cleaned up. This includes partially built +arrays. Exception specifications are now handled. Thrown objects are +now cleaned up all the time. We can now tell if we have an active +exception being thrown or not (__eh_type != 0). We use this to call +terminate if someone does a throw; without there being an active +exception object. uncaught_exception () works. Exception handling +should work right if you optimize. Exception handling should work with +-fpic or -fPIC. + +The below points out some flaws in g++'s exception handling, as it now +stands. + +Only exact type matching or reference matching of throw types works when +-fno-rtti is used. Only works on a SPARC (like Suns) (both -mflat and +-mno-flat models work), SPARClite, Hitachi SH, i386, arm, rs6000, +PowerPC, Alpha, mips, VAX, m68k and z8k machines. SPARC v9 may not +work. HPPA is mostly done, but throwing between a shared library and +user code doesn't yet work. Some targets have support for data-driven +unwinding. Partial support is in for all other machines, but a stack +unwinder called __unwind_function has to be written, and added to +libgcc2 for them. The new EH code doesn't rely upon the +__unwind_function for C++ code, instead it creates per function +unwinders right inside the function, unfortunately, on many platforms +the definition of RETURN_ADDR_RTX in the tm.h file for the machine port +is wrong. See below for details on __unwind_function. RTL_EXPRs for EH +cond variables for && and || exprs should probably be wrapped in +UNSAVE_EXPRs, and RTL_EXPRs tweaked so that they can be unsaved. + +We only do pointer conversions on exception matching a la 15.3 p2 case +3: `A handler with type T, const T, T&, or const T& is a match for a +throw-expression with an object of type E if [3]T is a pointer type and +E is a pointer type that can be converted to T by a standard pointer +conversion (_conv.ptr_) not involving conversions to pointers to private +or protected base classes.' when -frtti is given. + +We don't call delete on new expressions that die because the ctor threw +an exception. See except/18 for a test case. + +15.2 para 13: The exception being handled should be rethrown if control +reaches the end of a handler of the function-try-block of a constructor +or destructor, right now, it is not. + +15.2 para 12: If a return statement appears in a handler of +function-try-block of a constructor, the program is ill-formed, but this +isn't diagnosed. + +15.2 para 11: If the handlers of a function-try-block contain a jump +into the body of a constructor or destructor, the program is ill-formed, +but this isn't diagnosed. + +15.2 para 9: Check that the fully constructed base classes and members +of an object are destroyed before entering the handler of a +function-try-block of a constructor or destructor for that object. + +build_exception_variant should sort the incoming list, so that it +implements set compares, not exact list equality. Type smashing should +smash exception specifications using set union. + +Thrown objects are usually allocated on the heap, in the usual way. If +one runs out of heap space, throwing an object will probably never work. +This could be relaxed some by passing an __in_chrg parameter to track +who has control over the exception object. Thrown objects are not +allocated on the heap when they are pointer to object types. We should +extend it so that all small (<4*sizeof(void*)) objects are stored +directly, instead of allocated on the heap. + +When the backend returns a value, it can create new exception regions +that need protecting. The new region should rethrow the object in +context of the last associated cleanup that ran to completion. + +The structure of the code that is generated for C++ exception handling +code is shown below: + +@example +Ln: throw value; + copy value onto heap + jump throw (Ln, id, address of copy of value on heap) + + try @{ ++Lstart: the start of the main EH region +|... ... ++Lend: the end of the main EH region + @} catch (T o) @{ + ...1 + @} +Lresume: + nop used to make sure there is something before + the next region ends, if there is one +... ... + + jump Ldone +[ +Lmainhandler: handler for the region Lstart-Lend + cleanup +] zero or more, depending upon automatic vars with dtors ++Lpartial: +| jump Lover ++Lhere: + rethrow (Lhere, same id, same obj); +Lterm: handler for the region Lpartial-Lhere + call terminate +Lover: +[ + [ + call throw_type_match + if (eq) @{ + ] these lines disappear when there is no catch condition ++Lsregion2: +| ...1 +| jump Lresume +|Lhandler: handler for the region Lsregion2-Leregion2 +| rethrow (Lresume, same id, same obj); ++Leregion2 + @} +] there are zero or more of these sections, depending upon how many + catch clauses there are +----------------------------- expand_end_all_catch -------------------------- + here we have fallen off the end of all catch + clauses, so we rethrow to outer + rethrow (Lresume, same id, same obj); +----------------------------- expand_end_all_catch -------------------------- +[ +L1: maybe throw routine +] depending upon if we have expanded it or not +Ldone: + ret + +start_all_catch emits labels: Lresume, + +@end example + +The __unwind_function takes a pointer to the throw handler, and is +expected to pop the stack frame that was built to call it, as well as +the frame underneath and then jump to the throw handler. It must +restore all registers to their proper values as well as all other +machine state as determined by the context in which we are unwinding +into. The way I normally start is to compile: + + void *g; + foo(void* a) @{ g = a; @} + +with -S, and change the thing that alters the PC (return, or ret +usually) to not alter the PC, making sure to leave all other semantics +(like adjusting the stack pointer, or frame pointers) in. After that, +replicate the prologue once more at the end, again, changing the PC +altering instructions, and finally, at the very end, jump to `g'. + +It takes about a week to write this routine, if someone wants to +volunteer to write this routine for any architecture, exception support +for that architecture will be added to g++. Please send in those code +donations. One other thing that needs to be done, is to double check +that __builtin_return_address (0) works. + +@subsection Specific Targets + +For the alpha, the __unwind_function will be something resembling: + +@example +void +__unwind_function(void *ptr) +@{ + /* First frame */ + asm ("ldq $15, 8($30)"); /* get the saved frame ptr; 15 is fp, 30 is sp */ + asm ("bis $15, $15, $30"); /* reload sp with the fp we found */ + + /* Second frame */ + asm ("ldq $15, 8($30)"); /* fp */ + asm ("bis $15, $15, $30"); /* reload sp with the fp we found */ + + /* Return */ + asm ("ret $31, ($16), 1"); /* return to PTR, stored in a0 */ +@} +@end example + +@noindent +However, there are a few problems preventing it from working. First of +all, the gcc-internal function @code{__builtin_return_address} needs to +work given an argument of 0 for the alpha. As it stands as of August +30th, 1995, the code for @code{BUILT_IN_RETURN_ADDRESS} in @file{expr.c} +will definitely not work on the alpha. Instead, we need to define +the macros @code{DYNAMIC_CHAIN_ADDRESS} (maybe), +@code{RETURN_ADDR_IN_PREVIOUS_FRAME}, and definitely need a new +definition for @code{RETURN_ADDR_RTX}. + +In addition (and more importantly), we need a way to reliably find the +frame pointer on the alpha. The use of the value 8 above to restore the +frame pointer (register 15) is incorrect. On many systems, the frame +pointer is consistently offset to a specific point on the stack. On the +alpha, however, the frame pointer is pushed last. First the return +address is stored, then any other registers are saved (e.g., @code{s0}), +and finally the frame pointer is put in place. So @code{fp} could have +an offset of 8, but if the calling function saved any registers at all, +they add to the offset. + +The only places the frame size is noted are with the @samp{.frame} +directive, for use by the debugger and the OSF exception handling model +(useless to us), and in the initial computation of the new value for +@code{sp}, the stack pointer. For example, the function may start with: + +@example +lda $30,-32($30) +.frame $15,32,$26,0 +@end example + +@noindent +The 32 above is exactly the value we need. With this, we can be sure +that the frame pointer is stored 8 bytes less---in this case, at 24(sp)). +The drawback is that there is no way that I (Brendan) have found to let +us discover the size of a previous frame @emph{inside} the definition +of @code{__unwind_function}. + +So to accomplish exception handling support on the alpha, we need two +things: first, a way to figure out where the frame pointer was stored, +and second, a functional @code{__builtin_return_address} implementation +for except.c to be able to use it. + +Or just support DWARF 2 unwind info. + +@subsection New Backend Exception Support + +This subsection discusses various aspects of the design of the +data-driven model being implemented for the exception handling backend. + +The goal is to generate enough data during the compilation of user code, +such that we can dynamically unwind through functions at run time with a +single routine (@code{__throw}) that lives in libgcc.a, built by the +compiler, and dispatch into associated exception handlers. + +This information is generated by the DWARF 2 debugging backend, and +includes all of the information __throw needs to unwind an arbitrary +frame. It specifies where all of the saved registers and the return +address can be found at any point in the function. + +Major disadvantages when enabling exceptions are: + +@itemize @bullet +@item +Code that uses caller saved registers, can't, when flow can be +transferred into that code from an exception handler. In high performance +code this should not usually be true, so the effects should be minimal. + +@end itemize + +@subsection Backend Exception Support + +The backend must be extended to fully support exceptions. Right now +there are a few hooks into the alpha exception handling backend that +resides in the C++ frontend from that backend that allows exception +handling to work in g++. An exception region is a segment of generated +code that has a handler associated with it. The exception regions are +denoted in the generated code as address ranges denoted by a starting PC +value and an ending PC value of the region. Some of the limitations +with this scheme are: + +@itemize @bullet +@item +The backend replicates insns for such things as loop unrolling and +function inlining. Right now, there are no hooks into the frontend's +exception handling backend to handle the replication of insns. When +replication happens, a new exception region descriptor needs to be +generated for the new region. + +@item +The backend expects to be able to rearrange code, for things like jump +optimization. Any rearranging of the code needs have exception region +descriptors updated appropriately. + +@item +The backend can eliminate dead code. Any associated exception region +descriptor that refers to fully contained code that has been eliminated +should also be removed, although not doing this is harmless in terms of +semantics. + +@end itemize + +The above is not meant to be exhaustive, but does include all things I +have thought of so far. I am sure other limitations exist. + +Below are some notes on the migration of the exception handling code +backend from the C++ frontend to the backend. + +NOTEs are to be used to denote the start of an exception region, and the +end of the region. I presume that the interface used to generate these +notes in the backend would be two functions, start_exception_region and +end_exception_region (or something like that). The frontends are +required to call them in pairs. When marking the end of a region, an +argument can be passed to indicate the handler for the marked region. +This can be passed in many ways, currently a tree is used. Another +possibility would be insns for the handler, or a label that denotes a +handler. I have a feeling insns might be the best way to pass it. +Semantics are, if an exception is thrown inside the region, control is +transferred unconditionally to the handler. If control passes through +the handler, then the backend is to rethrow the exception, in the +context of the end of the original region. The handler is protected by +the conventional mechanisms; it is the frontend's responsibility to +protect the handler, if special semantics are required. + +This is a very low level view, and it would be nice is the backend +supported a somewhat higher level view in addition to this view. This +higher level could include source line number, name of the source file, +name of the language that threw the exception and possibly the name of +the exception. Kenner may want to rope you into doing more than just +the basics required by C++. You will have to resolve this. He may want +you to do support for non-local gotos, first scan for exception handler, +if none is found, allow the debugger to be entered, without any cleanups +being done. To do this, the backend would have to know the difference +between a cleanup-rethrower, and a real handler, if would also have to +have a way to know if a handler `matches' a thrown exception, and this +is frontend specific. + +The stack unwinder is one of the hardest parts to do. It is highly +machine dependent. The form that kenner seems to like was a couple of +macros, that would do the machine dependent grunt work. One preexisting +function that might be of some use is __builtin_return_address (). One +macro he seemed to want was __builtin_return_address, and the other +would do the hard work of fixing up the registers, adjusting the stack +pointer, frame pointer, arg pointer and so on. + + +@node Free Store, Mangling, Exception Handling, Top +@section Free Store + +@code{operator new []} adds a magic cookie to the beginning of arrays +for which the number of elements will be needed by @code{operator delete +[]}. These are arrays of objects with destructors and arrays of objects +that define @code{operator delete []} with the optional size_t argument. +This cookie can be examined from a program as follows: + +@example +typedef unsigned long size_t; +extern "C" int printf (const char *, ...); + +size_t nelts (void *p) +@{ + struct cookie @{ + size_t nelts __attribute__ ((aligned (sizeof (double)))); + @}; + + cookie *cp = (cookie *)p; + --cp; + + return cp->nelts; +@} + +struct A @{ + ~A() @{ @} +@}; + +main() +@{ + A *ap = new A[3]; + printf ("%ld\n", nelts (ap)); +@} +@end example + +@section Linkage +The linkage code in g++ is horribly twisted in order to meet two design goals: + +1) Avoid unnecessary emission of inlines and vtables. + +2) Support pedantic assemblers like the one in AIX. + +To meet the first goal, we defer emission of inlines and vtables until +the end of the translation unit, where we can decide whether or not they +are needed, and how to emit them if they are. + +@node Mangling, Vtables, Free Store, Top +@section Function name mangling for C++ and Java + +Both C++ and Jave provide overloaded function and methods, +which are methods with the same types but different parameter lists. +Selecting the correct version is done at compile time. +Though the overloaded functions have the same name in the source code, +they need to be translated into different assembler-level names, +since typical assemblers and linkers cannot handle overloading. +This process of encoding the parameter types with the method name +into a unique name is called @dfn{name mangling}. The inverse +process is called @dfn{demangling}. + +It is convenient that C++ and Java use compatible mangling schemes, +since the makes life easier for tools such as gdb, and it eases +integration between C++ and Java. + +Note there is also a standard "Jave Native Interface" (JNI) which +implements a different calling convention, and uses a different +mangling scheme. The JNI is a rather abstract ABI so Java can call methods +written in C or C++; +we are concerned here about a lower-level interface primarily +intended for methods written in Java, but that can also be used for C++ +(and less easily C). + +Note that on systems that follow BSD tradition, a C identifier @code{var} +would get "mangled" into the assembler name @samp{_var}. On such +systems, all other mangled names are also prefixed by a @samp{_} +which is not shown in the following examples. + +@subsection Method name mangling + +C++ mangles a method by emitting the function name, followed by @code{__}, +followed by encodings of any method qualifiers (such as @code{const}), +followed by the mangling of the method's class, +followed by the mangling of the parameters, in order. + +For example @code{Foo::bar(int, long) const} is mangled +as @samp{bar__C3Fooil}. + +For a constructor, the method name is left out. +That is @code{Foo::Foo(int, long) const} is mangled +as @samp{__C3Fooil}. + +GNU Java does the same. + +@subsection Primitive types + +The C++ types @code{int}, @code{long}, @code{short}, @code{char}, +and @code{long long} are mangled as @samp{i}, @samp{l}, +@samp{s}, @samp{c}, and @samp{x}, respectively. +The corresponding unsigned types have @samp{U} prefixed +to the mangling. The type @code{signed char} is mangled @samp{Sc}. + +The C++ and Java floating-point types @code{float} and @code{double} +are mangled as @samp{f} and @samp{d} respectively. + +The C++ @code{bool} type and the Java @code{boolean} type are +mangled as @samp{b}. + +The C++ @code{wchar_t} and the Java @code{char} types are +mangled as @samp{w}. + +The Java integral types @code{byte}, @code{short}, @code{int} +and @code{long} are mangled as @samp{c}, @samp{s}, @samp{i}, +and @samp{x}, respectively. + +C++ code that has included @code{javatypes.h} will mangle +the typedefs @code{jbyte}, @code{jshort}, @code{jint} +and @code{jlong} as respectively @samp{c}, @samp{s}, @samp{i}, +and @samp{x}. (This has not been implemented yet.) + +@subsection Mangling of simple names + +A simple class, package, template, or namespace name is +encoded as the number of characters in the name, followed by +the actual characters. Thus the class @code{Foo} +is encoded as @samp{3Foo}. + +If any of the characters in the name are not alphanumeric +(i.e not one of the standard ASCII letters, digits, or '_'), +or the initial character is a digit, then the name is +mangled as a sequence of encoded Unicode letters. +A Unicode encoding starts with a @samp{U} to indicate +that Unicode escapes are used, followed by the number of +bytes used by the Unicode encoding, followed by the bytes +representing the encoding. ASSCI letters and +non-initial digits are encoded without change. However, all +other characters (including underscore and initial digits) are +translated into a sequence starting with an underscore, +followed by the big-endian 4-hex-digit lower-case encoding of the character. + +If a method name contains Unicode-escaped characters, the +entire mangled method name is followed by a @samp{U}. + +For example, the method @code{X\u0319::M\u002B(int)} is encoded as +@samp{M_002b__U6X_0319iU}. + + +@subsection Pointer and reference types + +A C++ pointer type is mangled as @samp{P} followed by the +mangling of the type pointed to. + +A C++ reference type as mangled as @samp{R} followed by the +mangling of the type referenced. + +A Java object reference type is equivalent +to a C++ pointer parameter, so we mangle such an parameter type +as @samp{P} followed by the mangling of the class name. + +@subsection Squangled type compression + +Squangling (enabled with the @samp{-fsquangle} option), utilizes the +@samp{B} code to indicate reuse of a previously seen type within an +indentifier. Types are recognized in a left to right manner and given +increasing values, which are appended to the code in the standard +manner. Ie, multiple digit numbers are delimited by @samp{_} +characters. A type is considered to be any non primitive type, +regardless of whether its a parameter, template parameter, or entire +template. Certain codes are considered modifiers of a type, and are not +included as part of the type. These are the @samp{C}, @samp{V}, +@samp{P}, @samp{A}, @samp{R}, @samp{U} and @samp{u} codes, denoting +constant, volatile, pointer, array, reference, unsigned, and restrict. +These codes may precede a @samp{B} type in order to make the required +modifications to the type. + +For example: +@example +template class class1 @{ @}; + +template class class2 @{ @}; + +class class3 @{ @}; + +int f(class2 > a ,int b, const class1&c, class3 *d) @{ @} + + B0 -> class2 + B1 -> class1 + B2 -> class3 +@end example +Produces the mangled name @samp{f__FGt6class21Zt6class11Z6class3iRCB1PB2}. +The int parameter is a basic type, and does not receive a B encoding... + +@subsection Qualified names + +Both C++ and Java allow a class to be lexically nested inside another +class. C++ also supports namespaces (not yet implemented by G++). +Java also supports packages. + +These are all mangled the same way: First the letter @samp{Q} +indicates that we are emitting a qualified name. +That is followed by the number of parts in the qualified name. +If that number is 9 or less, it is emitted with no delimiters. +Otherwise, an underscore is written before and after the count. +Then follows each part of the qualified name, as described above. + +For example @code{Foo::\u0319::Bar} is encoded as +@samp{Q33FooU5_03193Bar}. + +Squangling utilizes the the letter @samp{K} to indicate a +remembered portion of a qualified name. As qualified names are processed +for an identifier, the names are numbered and remembered in a +manner similar to the @samp{B} type compression code. +Names are recognized left to right, and given increasing values, which are +appended to the code in the standard manner. ie, multiple digit numbers +are delimited by @samp{_} characters. + +For example +@example +class Andrew +@{ + class WasHere + @{ + class AndHereToo + @{ + @}; + @}; +@}; + +f(Andrew&r1, Andrew::WasHere& r2, Andrew::WasHere::AndHereToo& r3) @{ @} + + K0 -> Andrew + K1 -> Andrew::WasHere + K2 -> Andrew::WasHere::AndHereToo +@end example +Function @samp{f()} would be mangled as : +@samp{f__FR6AndrewRQ2K07WasHereRQ2K110AndHereToo} + +There are some occasions when either a @samp{B} or @samp{K} code could +be chosen, preference is always given to the @samp{B} code. Ie, the example +in the section on @samp{B} mangling could have used a @samp{K} code +instead of @samp{B2}. + +@subsection Templates + +A class template instantiation is encoded as the letter @samp{t}, +followed by the encoding of the template name, followed +the number of template parameters, followed by encoding of the template +parameters. If a template parameter is a type, it is written +as a @samp{Z} followed by the encoding of the type. + +A function template specialization (either an instantiation or an +explicit specialization) is encoded by an @samp{H} followed by the +encoding of the template parameters, as described above, followed by an +@samp{_}, the encoding of the argument types to the template function +(not the specialization), another @samp{_}, and the return type. (Like +the argument types, the return type is the return type of the function +template, not the specialization.) Template parameters in the argument +and return types are encoded by an @samp{X} for type parameters, or a +@samp{Y} for constant parameters, an index indicating their position +in the template parameter list declaration, and their template depth. + +@subsection Arrays + +C++ array types are mangled by emitting @samp{A}, followed by +the length of the array, followed by an @samp{_}, followed by +the mangling of the element type. Of course, normally +array parameter types decay into a pointer types, so you +don't see this. + +Java arrays are objects. A Java type @code{T[]} is mangled +as if it were the C++ type @code{JArray}. +For example @code{java.lang.String[]} is encoded as +@samp{Pt6JArray1ZPQ34java4lang6String}. + +@subsection Static fields + +Both C++ and Java classes can have static fields. +These are allocated statically, and are shared among all instances. + +The mangling starts with a prefix (@samp{_} in most systems), which is +followed by the mangling +of the class name, followed by the "joiner" and finally the field name. +The joiner (see @code{JOINER} in @code{cp-tree.h}) is a special +separator character. For historical reasons (and idiosyncracies +of assembler syntax) it can @samp{$} or @samp{.} (or even +@samp{_} on a few systems). If the joiner is @samp{_} then the prefix +is @samp{__static_} instead of just @samp{_}. + +For example @code{Foo::Bar::var} (or @code{Foo.Bar.var} in Java syntax) +would be encoded as @samp{_Q23Foo3Bar$var} or @samp{_Q23Foo3Bar.var} +(or rarely @samp{__static_Q23Foo3Bar_var}). + +If the name of a static variable needs Unicode escapes, +the Unicode indicator @samp{U} comes before the "joiner". +This @code{\u1234Foo::var\u3445} becomes @code{_U8_1234FooU.var_3445}. + +@subsection Table of demangling code characters + +The following special characters are used in mangling: + +@table @samp +@item A +Indicates a C++ array type. + +@item b +Encodes the C++ @code{bool} type, +and the Java @code{boolean} type. + +@item B +Used for squangling. Similar in concept to the 'T' non-squangled code. + +@item c +Encodes the C++ @code{char} type, and the Java @code{byte} type. + +@item C +A modifier to indicate a @code{const} type. +Also used to indicate a @code{const} member function +(in which cases it precedes the encoding of the method's class). + +@item d +Encodes the C++ and Java @code{double} types. + +@item e +Indicates extra unknown arguments @code{...}. + +@item E +Indicates the opening parenthesis of an expression. + +@item f +Encodes the C++ and Java @code{float} types. + +@item F +Used to indicate a function type. + +@item H +Used to indicate a template function. + +@item i +Encodes the C++ and Java @code{int} types. + +@item I +Encodes typedef names of the form @code{int@var{n}_t}, where @var{n} is a +positive decimal number. The @samp{I} is followed by either two +hexidecimal digits, which encode the value of @var{n}, or by an +arbitrary number of hexidecimal digits between underscores. For +example, @samp{I40} encodes the type @code{int64_t}, and @samp{I_200_} +encodes the type @code{int512_t}. + +@item J +Indicates a complex type. + +@item K +Used by squangling to compress qualified names. + +@item l +Encodes the C++ @code{long} type. + +@item n +Immediate repeated type. Followed by the repeat count. + +@item N +Repeated type. Followed by the repeat count of the repeated type, +followed by the type index of the repeated type. Due to a bug in +g++ 2.7.2, this is only generated if index is 0. Superceded by +@samp{n} when squangling. + +@item P +Indicates a pointer type. Followed by the type pointed to. + +@item Q +Used to mangle qualified names, which arise from nested classes. +Also used for namespaces. +In Java used to mangle package-qualified names, and inner classes. + +@item r +Encodes the GNU C++ @code{long double} type. + +@item R +Indicates a reference type. Followed by the referenced type. + +@item s +Encodes the C++ and java @code{short} types. + +@item S +A modifier that indicates that the following integer type is signed. +Only used with @code{char}. + +Also used as a modifier to indicate a static member function. + +@item t +Indicates a template instantiation. + +@item T +A back reference to a previously seen type. + +@item U +A modifier that indicates that the following integer type is unsigned. +Also used to indicate that the following class or namespace name +is encoded using Unicode-mangling. + +@item u +The @code{restrict} type qualifier. + +@item v +Encodes the C++ and Java @code{void} types. + +@item V +A modifier for a @code{volatile} type or method. + +@item w +Encodes the C++ @code{wchar_t} type, and the Java @code{char} types. + +@item W +Indicates the closing parenthesis of an expression. + +@item x +Encodes the GNU C++ @code{long long} type, and the Java @code{long} type. + +@item X +Encodes a template type parameter, when part of a function type. + +@item Y +Encodes a template constant parameter, when part of a function type. + +@item Z +Used for template type parameters. + +@end table + +The letters @samp{G}, @samp{M}, @samp{O}, and @samp{p} +also seem to be used for obscure purposes ... + +@node Vtables, Concept Index, Mangling, Top +@section Virtual Tables + +In order to invoke virtual functions, GNU C++ uses virtual tables. Each +virtual function gets an index, and the table entry points to the +overridden function to call. Sometimes, and adjustment to the this +pointer has to be made before calling a virtual function: + +@example +struct A@{ + int i; + virtual void foo(); +@}; + +struct B@{ + int j; + virtual void bar(); +@}; + +struct C:A,B@{ + virtual void bar(); +@}; + +void C::bar() +@{ + i++; +@} + +int main() +@{ + C *c = new C; + B *b = c; + c->bar(); +@} +@end example + +Here, casting from @samp{c} to @samp{b} adds an offset. When @samp{bar} +is called, this offset needs to be subtracted, so that @samp{C::bar} can +properly access @samp{i}. One approach of achieving this is to use +@emph{thunks}, which are small half-functions put into the virtual +table. The modify the first argument (the @samp{this} pointer), and then +jump into the real function. + +The other (traditional) approach is to have an additional integer in the +virtual table which is added to this. This is an additional overhead +both at the function call, and in the size of virtual tables: In the +case of single inheritance (or for the first base class), these integers +will always be zero. + +@subsection Virtual Base Classes with Virtual Tables + +In case of virtual bases, the code is even more +complicated. Constructors and destructors need to know whether they are +"in charge" of the virtual bases, and an implicit integer +@samp{__in_chrg} for that purpose. + +@example +struct A@{ + int i; + virtual void bar(); + void call_bar()@{bar();@} +@}; + +struct B:virtual A@{ + B(); + int j; + virtual void bar(); +@}; + +B::B()@{ + call_bar(); +@} + +struct C@{ + int k; +@}; + +struct D:C,B@{ + int l; + virtual void bar(); +@}; + +@end example + +When constructing an instance of B, it will have the following layout: +@samp{vbase pointer to A}, @samp{j}, @samp{A virtual table}, @samp{i}. +On a 32-bit machine, downcasting from @samp{A*} to @samp{B*} would need +to subtract 8, which would be the thunk executed when calling +@samp{B::bar} inside @samp{call_bar}. + +When constructing an instance of D, it will have a different layout: +@samp{k}, @samp{vbase pointer to A}, @samp{j}, @samp{l}, @samp{A virtual +table}, @samp{i}. So, when downcasting from @samp{A*} to @samp{B*} in a +@samp{D} object, the offset would be @samp{12}. + +This means that during construction of the @samp{B} base of a @samp{D} +object, a virtual table is needed which has a @samp{-12} thunk to +@samp{B::bar}. This is @emph{only} needed during construction and +destruction, as the full object will use a @samp{-16} thunk to +@samp{D::bar}. + +In order to implement this, the compiler generates an implicit argument +(in addition to @code{__in_chrg}): the virtual list argument +@code{__vlist}. This is a list of virtual tables needed during +construction and destruction. The virtual pointers are ordered in the +way they are used during construction; the destructors will process the +array in reverse order. The ordering is as follows: +@itemize @bullet +@item +If the class is in charge, the vlist starts with virtual table pointers +for the virtual bases that have virtual bases themselves. Here, only +@emph{polymorphic} virtual bases (pvbases) are interesting: if a vbase +has no virtual functions, it doesn't have a virtual table. + +@item +Next, the vlist has virtual tables for the initialization of the +non-virtual bases. These bases are not in charge, so the layout is +recursive, but ignores virtual bases during recursion. + +@item +Next, there is a number of virtual tables for each virtual base. These +are sorted in the order in which virtual bases are constructed. Each +virtual base may have more than one @code{vfield}, and therefore require +more than one @code{vtable}. The order of vtables is the same as used +when initializing vfields of non-virtual bases in a constructor. +@end itemize + +The compiler emits a virtual table list in a variable mangled as +@code{__vl.classname}. + +Class with virtual bases, but without pvbases, only have the +@code{__in_chrg} argument to their ctors and dtors: they don't have any +vfields in the vbases to initialize. + +A further problem arises with virtual destructors: A destructor +typically has only the @code{__in_chrg} argument, which also indicates +whether the destructor should call @code{operator delete}. A dtor of a +class with pvbases has an additional argument. Unfortunately, a caller +of a virtual dtor might not know whether to pass that argument or not. +Therefore, the dtor processes the @code{__vlist} argument in an +automatic variable, which is initialized from the class' vlist if the +__in_chrg flag has a zero value in bit 2 (bit mask 4), or from the +argument @code{__vlist1} if bit 2 of the __in_chrg parameter is set to +one. + +@subsection Specification of non-thunked vtables + +In the traditional implementation of vtables, each slot contains three +fields: The offset to be added to the this pointer before invoking a +virtual function, an unused field that is always zero, and the pointer +to the virtual function. The first two fields are typically 16 bits +wide. The unused field is called `index'; it may be non-zero in +pointer-to-member-functions, which use the same layout. + +The virtual table then is an array of vtable slots. The first slot is +always the virtual type info function, the other slots are in the order +in which the virtual functions appear in the class declaration. + +If a class has base classes, it may inherit other bases' vfields. Each +class may have a primary vfield; the primary vfield of the derived class +is the primary vfield of the left-most non-virtual base class. If a +class inherits a primary vfield, any new virtual functions in the +derived class are appended to the virtual table of the primary +vfield. If there are new virtual functions in the derived class, and no +primary vfield is inherited, a new vfield is introduced which becomes +primary. The redefined virtual functions fill the vtable slots inherited +from the base; new virtual functions are put into the primary vtable in +the order of declaration. If no new virtual functions are introduced, no +primary vfield is allocated. + +In a base class that has pvbases, virtual tables are needed which are +used only in the constructor (see example above). At run-time, the +virtual tables of the base class are adjusted, to reflect the new offset +of the pvbase. The compiler knows statically what offset the pvbase has +for a complete object. At run-time, the offset of the pvbase can be +extracted from the vbase pointer, which is set in the constructor of the +complete object. These two offsets result in a delta, which is used to +adjust the deltas in the vtable (the adjustment might be different for +different vtable slots). To adjust the vtables, the compiler emits code +that creates a vtable on the stack. This vtable is initialized with the +vtable for the complete base type, and then adjusted. + +In order to call a virtual function, the compiler gets the offset field +from the vtable entry, and adds it to the this pointer. It then +indirectly calls the virtual function pointer, passing the adjusted this +pointer, and any arguments the virtual function may have. + +To implement dynamic casting, the dynamic_cast function needs typeinfos +for the complete type, and the pointer to the complete type. The +typeinfo pointer is obtained by calling the virtual typeinfo function +(which doesn't take a this parameter). The pointer to the complete +object is obtained by adding the offset of the virtual typeinfo vtable +slot, since this virtual function is always implemented in the complete +object. + +@subsection Specification of thunked vtables + +For vtable thunks, each slot only consists of a pointer to the virtual +function, which might be a thunk function. The first slot in the vtable +is an offset of the this pointer to the complete object, which is needed +as a parameter to __dynamic_cast. The second slot is the virtual +typeinfo function. All other slots are allocated with the same procedure +as in the non-thunked case. Allocation of vfields also uses the same +procedure as described above. + +If the virtual function needs an adjusted this pointer, a thunk function +is emitted. If supported by the target architecture, this is only a +half-function. Such a thunk has no stack frame; it merely adjusts the +first argument of the function, and then directly branches into the +implementation of the virtual function. If the architecture does not +support half-functions (i.e. if ASM_OUTPUT_MI_THUNK is not defined), the +compiler emits a wrapper function, which copies all arguments, adjust +the this pointer, and then calls the original function. Since objects of +non-aggregate type are passed by invisible reference, this copies only +POD arguments. The approach fails for virtual functions with a variable +number of arguments. + +In order to support the vtables needed in base constructors with +pvbases, the compiler passes an implicit __vlist argument as described +above, if the version 2 thunks are used. For version 1 thunks, the base +class constructor will fill in the vtables for the complete base class, +which will incorrectly adjust the this pointer, leading to a dynamic +error. + +@node Concept Index, , Vtables, Top + +@section Concept Index + +@printindex cp + +@bye Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/gxxint.texi ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/init.c =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/init.c (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/init.c (revision 60969) @@ -0,0 +1,3499 @@ +/* Handle initialization things in C++. + Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@cygnus.com) + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* High-level class interface. */ + +#include "config.h" +#include "system.h" +#include "tree.h" +#include "rtl.h" +#include "cp-tree.h" +#include "flags.h" +#include "output.h" +#include "except.h" +#include "expr.h" +#include "toplev.h" + +/* In C++, structures with well-defined constructors are initialized by + those constructors, unasked. CURRENT_BASE_INIT_LIST + holds a list of stmts for a BASE_INIT term in the grammar. + This list has one element for each base class which must be + initialized. The list elements are [basename, init], with + type basetype. This allows the possibly anachronistic form + (assuming d : a, b, c) "d (int a) : c(a+5), b (a-4), a (a+3)" + where each successive term can be handed down the constructor + line. Perhaps this was not intended. */ +tree current_base_init_list, current_member_init_list; + +static void expand_aggr_vbase_init_1 PROTO((tree, tree, tree, tree)); +static void construct_virtual_bases PROTO((tree, tree, tree, tree, tree)); +static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int)); +static void expand_default_init PROTO((tree, tree, tree, tree, int)); +static tree build_vec_delete_1 PROTO((tree, tree, tree, tree, tree, + int)); +static void perform_member_init PROTO((tree, tree, tree, int)); +static void sort_base_init PROTO((tree, tree *, tree *)); +static tree build_builtin_delete_call PROTO((tree)); +static int member_init_ok_or_else PROTO((tree, tree, const char *)); +static void expand_virtual_init PROTO((tree, tree)); +static tree sort_member_init PROTO((tree)); +static tree initializing_context PROTO((tree)); +static void expand_vec_init_try_block PROTO((tree)); +static void expand_vec_init_catch_clause PROTO((tree, tree, tree, tree)); +static tree build_java_class_ref PROTO((tree)); +static void expand_cleanup_for_base PROTO((tree, tree, tree)); +static int pvbasecount PROTO((tree, int)); + +/* Cache the identifier nodes for the magic field of a new cookie. */ +static tree nc_nelts_field_id; + +static tree minus_one; + +/* Set up local variable for this file. MUST BE CALLED AFTER + INIT_DECL_PROCESSING. */ + +static tree BI_header_type, BI_header_size; + +void init_init_processing () +{ + tree fields[1]; + + minus_one = build_int_2 (-1, -1); + + /* Define the structure that holds header information for + arrays allocated via operator new. */ + BI_header_type = make_lang_type (RECORD_TYPE); + nc_nelts_field_id = get_identifier ("nelts"); + fields[0] = build_lang_field_decl (FIELD_DECL, nc_nelts_field_id, sizetype); + finish_builtin_type (BI_header_type, "__new_cookie", fields, + 0, double_type_node); + BI_header_size = size_in_bytes (BI_header_type); +} + +/* Subroutine of emit_base_init. For BINFO, initialize all the + virtual function table pointers, except those that come from + virtual base classes. Initialize binfo's vtable pointer, if + INIT_SELF is true. CAN_ELIDE is true when we know that all virtual + function table pointers in all bases have been initialized already, + probably because their constructors have just be run. ADDR is the + pointer to the object whos vtables we are going to initialize. + + REAL_BINFO is usually the same as BINFO, except when addr is not of + pointer to the type of the real derived type that we want to + initialize for. This is the case when addr is a pointer to a sub + object of a complete object, and we only want to do part of the + complete object's initialization of vtable pointers. This is done + for all virtual table pointers in virtual base classes. REAL_BINFO + is used to find the BINFO_VTABLE that we initialize with. BINFO is + used for conversions of addr to subobjects. + + BINFO_TYPE (real_binfo) must be BINFO_TYPE (binfo). + + Relies upon binfo being inside TYPE_BINFO (TREE_TYPE (TREE_TYPE + (addr))). */ + +void +expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) + tree real_binfo, binfo, addr; + int init_self, can_elide; +{ + tree real_binfos = BINFO_BASETYPES (real_binfo); + tree binfos = BINFO_BASETYPES (binfo); + int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0; + + for (i = 0; i < n_baselinks; i++) + { + tree real_base_binfo = TREE_VEC_ELT (real_binfos, i); + tree base_binfo = TREE_VEC_ELT (binfos, i); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo)); + if (! TREE_VIA_VIRTUAL (real_base_binfo)) + expand_direct_vtbls_init (real_base_binfo, base_binfo, + is_not_base_vtable, can_elide, addr); + } +#if 0 + /* Before turning this on, make sure it is correct. */ + if (can_elide && ! BINFO_MODIFIED (binfo)) + return; +#endif + /* Should we use something besides CLASSTYPE_VFIELDS? */ + if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo))) + { + tree base_ptr = convert_pointer_to_real (binfo, addr); + expand_virtual_init (real_binfo, base_ptr); + } +} + +/* 348 - 351 */ +/* Subroutine of emit_base_init. */ + +static void +perform_member_init (member, name, init, explicit) + tree member, name, init; + int explicit; +{ + tree decl; + tree type = TREE_TYPE (member); + + expand_start_target_temps (); + + if (TYPE_NEEDS_CONSTRUCTING (type) + || (init && TYPE_HAS_CONSTRUCTOR (type))) + { + /* Since `init' is already a TREE_LIST on the current_member_init_list, + only build it into one if we aren't already a list. */ + if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST) + init = build_expr_list (NULL_TREE, init); + + decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit); + + if (explicit + && TREE_CODE (type) == ARRAY_TYPE + && init != NULL_TREE + && TREE_CHAIN (init) == NULL_TREE + && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE) + { + /* Initialization of one array from another. */ + expand_vec_init (TREE_OPERAND (decl, 1), decl, + array_type_nelts (type), TREE_VALUE (init), 1); + } + else + expand_aggr_init (decl, init, 0); + } + else + { + if (init == NULL_TREE) + { + if (explicit) + { + /* default-initialization. */ + if (AGGREGATE_TYPE_P (type)) + init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); + else if (TREE_CODE (type) == REFERENCE_TYPE) + { + cp_error ("default-initialization of `%#D', which has reference type", + member); + init = error_mark_node; + } + else + init = integer_zero_node; + } + /* member traversal: note it leaves init NULL */ + else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE) + cp_pedwarn ("uninitialized reference member `%D'", member); + } + else if (TREE_CODE (init) == TREE_LIST) + { + /* There was an explicit member initialization. Do some + work in that case. */ + if (TREE_CHAIN (init)) + { + warning ("initializer list treated as compound expression"); + init = build_compound_expr (init); + } + else + init = TREE_VALUE (init); + } + + /* We only build this with a null init if we got it from the + current_member_init_list. */ + if (init || explicit) + { + decl = build_component_ref (current_class_ref, name, NULL_TREE, + explicit); + expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); + } + } + + expand_end_target_temps (); + free_temp_slots (); + + if (TYPE_NEEDS_DESTRUCTOR (type)) + { + tree expr; + + /* All cleanups must be on the function_obstack. */ + push_obstacks_nochange (); + resume_temporary_allocation (); + + expr = build_component_ref (current_class_ref, name, NULL_TREE, + explicit); + expr = build_delete (type, expr, integer_zero_node, + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); + + if (expr != error_mark_node) + add_partial_entry (expr); + + pop_obstacks (); + } +} + +extern int warn_reorder; + +/* Subroutine of emit_member_init. */ + +static tree +sort_member_init (t) + tree t; +{ + tree x, member, name, field; + tree init_list = NULL_TREE; + int last_pos = 0; + tree last_field = NULL_TREE; + + for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member)) + { + int pos; + + /* member could be, for example, a CONST_DECL for an enumerated + tag; we don't want to try to initialize that, since it already + has a value. */ + if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member)) + continue; + + for (x = current_member_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos) + { + /* If we cleared this out, then pay no attention to it. */ + if (TREE_PURPOSE (x) == NULL_TREE) + continue; + name = TREE_PURPOSE (x); + +#if 0 + /* This happens in templates, since the IDENTIFIER is replaced + with the COMPONENT_REF in tsubst_expr. */ + field = (TREE_CODE (name) == COMPONENT_REF + ? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name)); +#else + /* Let's find out when this happens. */ + my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 348); + field = IDENTIFIER_CLASS_VALUE (name); +#endif + + /* If one member shadows another, get the outermost one. */ + if (TREE_CODE (field) == TREE_LIST) + field = TREE_VALUE (field); + + if (field == member) + { + if (warn_reorder) + { + if (pos < last_pos) + { + cp_warning_at ("member initializers for `%#D'", last_field); + cp_warning_at (" and `%#D'", field); + warning (" will be re-ordered to match declaration order"); + } + last_pos = pos; + last_field = field; + } + + /* Make sure we won't try to work on this init again. */ + TREE_PURPOSE (x) = NULL_TREE; + x = build_tree_list (name, TREE_VALUE (x)); + goto got_it; + } + } + + /* If we didn't find MEMBER in the list, create a dummy entry + so the two lists (INIT_LIST and the list of members) will be + symmetrical. */ + x = build_tree_list (NULL_TREE, NULL_TREE); + got_it: + init_list = chainon (init_list, x); + } + + /* Initializers for base members go at the end. */ + for (x = current_member_init_list ; x ; x = TREE_CHAIN (x)) + { + name = TREE_PURPOSE (x); + if (name) + { + if (purpose_member (name, init_list)) + { + cp_error ("multiple initializations given for member `%D'", + IDENTIFIER_CLASS_VALUE (name)); + continue; + } + + init_list = chainon (init_list, + build_tree_list (name, TREE_VALUE (x))); + TREE_PURPOSE (x) = NULL_TREE; + } + } + + return init_list; +} + +static void +sort_base_init (t, rbase_ptr, vbase_ptr) + tree t, *rbase_ptr, *vbase_ptr; +{ + tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); + int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + int i; + tree x; + tree last; + + /* For warn_reorder. */ + int last_pos = 0; + tree last_base = NULL_TREE; + + tree rbases = NULL_TREE; + tree vbases = NULL_TREE; + + /* First walk through and splice out vbase and invalid initializers. + Also replace names with binfos. */ + + last = tree_cons (NULL_TREE, NULL_TREE, current_base_init_list); + for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x)) + { + tree basetype = TREE_PURPOSE (x); + tree binfo = NULL_TREE; + + if (basetype == NULL_TREE) + { + /* Initializer for single base class. Must not + use multiple inheritance or this is ambiguous. */ + switch (n_baseclasses) + { + case 0: + cp_error ("`%T' does not have a base class to initialize", + current_class_type); + return; + case 1: + break; + default: + cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance", + current_class_type); + return; + } + binfo = TREE_VEC_ELT (binfos, 0); + } + else if (is_aggr_type (basetype, 1)) + { + binfo = binfo_or_else (basetype, t); + if (binfo == NULL_TREE) + continue; + + /* Virtual base classes are special cases. Their initializers + are recorded with this constructor, and they are used when + this constructor is the top-level constructor called. */ + if (TREE_VIA_VIRTUAL (binfo)) + { + tree v = CLASSTYPE_VBASECLASSES (t); + while (BINFO_TYPE (v) != BINFO_TYPE (binfo)) + v = TREE_CHAIN (v); + + vbases = tree_cons (v, TREE_VALUE (x), vbases); + continue; + } + else + { + /* Otherwise, if it is not an immediate base class, complain. */ + for (i = n_baseclasses-1; i >= 0; i--) + if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i))) + break; + if (i < 0) + { + cp_error ("`%T' is not an immediate base class of `%T'", + basetype, current_class_type); + continue; + } + } + } + else + my_friendly_abort (365); + + TREE_PURPOSE (x) = binfo; + TREE_CHAIN (last) = x; + last = x; + } + TREE_CHAIN (last) = NULL_TREE; + + /* Now walk through our regular bases and make sure they're initialized. */ + + for (i = 0; i < n_baseclasses; ++i) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + int pos; + + if (TREE_VIA_VIRTUAL (base_binfo)) + continue; + + for (x = current_base_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos) + { + tree binfo = TREE_PURPOSE (x); + + if (binfo == NULL_TREE) + continue; + + if (binfo == base_binfo) + { + if (warn_reorder) + { + if (pos < last_pos) + { + cp_warning_at ("base initializers for `%#T'", last_base); + cp_warning_at (" and `%#T'", BINFO_TYPE (binfo)); + warning (" will be re-ordered to match inheritance order"); + } + last_pos = pos; + last_base = BINFO_TYPE (binfo); + } + + /* Make sure we won't try to work on this init again. */ + TREE_PURPOSE (x) = NULL_TREE; + x = build_tree_list (binfo, TREE_VALUE (x)); + goto got_it; + } + } + + /* If we didn't find BASE_BINFO in the list, create a dummy entry + so the two lists (RBASES and the list of bases) will be + symmetrical. */ + x = build_tree_list (NULL_TREE, NULL_TREE); + got_it: + rbases = chainon (rbases, x); + } + + *rbase_ptr = rbases; + *vbase_ptr = vbases; +} + +/* Invoke a base-class destructor. REF is the object being destroyed, + BINFO is the base class, and DTOR_ARG indicates whether the base + class should invoke delete. */ + +tree +build_base_dtor_call (ref, binfo, dtor_arg) + tree ref, binfo, dtor_arg; +{ + tree args = NULL_TREE; + tree vlist = lookup_name (vlist_identifier, 0); + tree call, decr; + + if (TYPE_USES_PVBASES (BINFO_TYPE (binfo))) + { + args = expr_tree_cons (NULL_TREE, vlist, args); + dtor_arg = build (BIT_IOR_EXPR, integer_type_node, + dtor_arg, build_int_2 (4, 0)); + dtor_arg = fold (dtor_arg); + } + args = expr_tree_cons (NULL_TREE, dtor_arg, args); + call = build_scoped_method_call (ref, binfo, dtor_identifier, args); + + if (!TYPE_USES_PVBASES (BINFO_TYPE (binfo))) + /* For plain inheritance, do not try to adjust __vlist. */ + return call; + + /* Now decrement __vlist by the number of slots consumed by the base + dtor. */ + decr = build_int_2 (pvbasecount (BINFO_TYPE (binfo), 0), 0); + decr = build_binary_op (MINUS_EXPR, vlist, decr); + decr = build_modify_expr (vlist, NOP_EXPR, decr); + + return build (COMPOUND_EXPR, void_type_node, call, decr); +} + +/* Return the number of vlist entries needed to initialize TYPE, + depending on whether it is IN_CHARGE. */ + +static int +pvbasecount (type, in_charge) + tree type; + int in_charge; +{ + int i; + int result = 0; + tree vbase; + + for (vbase = (CLASSTYPE_VBASECLASSES (type)); vbase; + vbase = TREE_CHAIN (vbase)) + { + result += list_length (CLASSTYPE_VFIELDS (BINFO_TYPE (vbase))); + if (in_charge) + result += pvbasecount (BINFO_TYPE (vbase), 0); + } + + for (i=0; i < CLASSTYPE_N_BASECLASSES (type); i++) + { + tree base = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i); + if (TREE_VIA_VIRTUAL (base)) + continue; + result += pvbasecount (BINFO_TYPE (base), 0); + } + return result; +} + +void +init_vlist (t) + tree t; +{ + char *name; + tree expr; + tree vlist = lookup_name (vlist_identifier, 0); + + name = alloca (strlen (VLIST_NAME_FORMAT) + + TYPE_ASSEMBLER_NAME_LENGTH (t) + 2); + sprintf (name, VLIST_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (t)); + + expr = get_identifier (name); + expr = lookup_name (expr, 0); + expr = build1 (ADDR_EXPR, TREE_TYPE (vlist), expr); + if (DECL_DESTRUCTOR_FOR_PVBASE_P (current_function_decl)) + /* Move to the end of the vlist. */ + expr = build_binary_op (PLUS_EXPR, expr, + build_int_2 (pvbasecount (t, 1), 0)); + expand_expr_stmt (build_modify_expr (vlist, NOP_EXPR, expr)); +} + +/* Perform whatever initializations have yet to be done on the base + class of the class variable. These actions are in the global + variable CURRENT_BASE_INIT_LIST. Such an action could be + NULL_TREE, meaning that the user has explicitly called the base + class constructor with no arguments. + + If there is a need for a call to a constructor, we must surround + that call with a pushlevel/poplevel pair, since we are technically + at the PARM level of scope. + + Argument IMMEDIATELY, if zero, forces a new sequence to be + generated to contain these new insns, so it can be emitted later. + This sequence is saved in the global variable BASE_INIT_EXPR. + Otherwise, the insns are emitted into the current sequence. + + Note that emit_base_init does *not* initialize virtual base + classes. That is done specially, elsewhere. */ + +extern tree base_init_expr, rtl_expr_chain; + +void +emit_base_init (t, immediately) + tree t; + int immediately; +{ + tree member; + tree mem_init_list; + tree rbase_init_list, vbase_init_list; + tree t_binfo = TYPE_BINFO (t); + tree binfos = BINFO_BASETYPES (t_binfo); + int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; + tree expr = NULL_TREE; + tree vlist = lookup_name (vlist_identifier, 0); + + if (! immediately) + { + int momentary; + do_pending_stack_adjust (); + /* Make the RTL_EXPR node temporary, not momentary, + so that rtl_expr_chain doesn't become garbage. */ + momentary = suspend_momentary (); + expr = make_node (RTL_EXPR); + resume_momentary (momentary); + start_sequence_for_rtl_expr (expr); + } + + if (write_symbols == NO_DEBUG) + /* As a matter of principle, `start_sequence' should do this. */ + emit_note (0, -1); + else + /* Always emit a line number note so we can step into constructors. */ + emit_line_note_force (DECL_SOURCE_FILE (current_function_decl), + DECL_SOURCE_LINE (current_function_decl)); + + mem_init_list = sort_member_init (t); + current_member_init_list = NULL_TREE; + + sort_base_init (t, &rbase_init_list, &vbase_init_list); + current_base_init_list = NULL_TREE; + + /* First, initialize the virtual base classes, if we are + constructing the most-derived object. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (t)) + { + tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl)); + construct_virtual_bases (t, current_class_ref, current_class_ptr, + vbase_init_list, first_arg); + } + + /* Now, perform initialization of non-virtual base classes. */ + for (i = 0; i < n_baseclasses; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree init = void_list_node; + + if (TREE_VIA_VIRTUAL (base_binfo)) + continue; + + my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo, + 999); + + if (TREE_PURPOSE (rbase_init_list)) + init = TREE_VALUE (rbase_init_list); + else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo))) + { + init = NULL_TREE; + if (extra_warnings && copy_args_p (current_function_decl)) + cp_warning ("base class `%#T' should be explicitly initialized in the copy constructor", + BINFO_TYPE (base_binfo)); + } + + if (init != void_list_node) + { + expand_start_target_temps (); + + member = convert_pointer_to_real (base_binfo, current_class_ptr); + expand_aggr_init_1 (base_binfo, NULL_TREE, + build_indirect_ref (member, NULL_PTR), init, + LOOKUP_NORMAL); + + expand_end_target_temps (); + free_temp_slots (); + } + + expand_cleanup_for_base (base_binfo, vlist, NULL_TREE); + rbase_init_list = TREE_CHAIN (rbase_init_list); + } + + /* Initialize all the virtual function table fields that + do come from virtual base classes. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (t)) + expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr); + + /* Initialize all the virtual function table fields that + do not come from virtual base classes. */ + expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr); + + for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) + { + tree init, name; + int from_init_list; + + /* member could be, for example, a CONST_DECL for an enumerated + tag; we don't want to try to initialize that, since it already + has a value. */ + if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member)) + continue; + + /* See if we had a user-specified member initialization. */ + if (TREE_PURPOSE (mem_init_list)) + { + name = TREE_PURPOSE (mem_init_list); + init = TREE_VALUE (mem_init_list); + from_init_list = 1; + +#if 0 + if (TREE_CODE (name) == COMPONENT_REF) + name = DECL_NAME (TREE_OPERAND (name, 1)); +#else + /* Also see if it's ever a COMPONENT_REF here. If it is, we + need to do `expand_assignment (name, init, 0, 0);' and + a continue. */ + my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349); +#endif + } + else + { + name = DECL_NAME (member); + init = DECL_INITIAL (member); + + from_init_list = 0; + + /* Effective C++ rule 12. */ + if (warn_ecpp && init == NULL_TREE + && !DECL_ARTIFICIAL (member) + && TREE_CODE (TREE_TYPE (member)) != ARRAY_TYPE) + cp_warning ("`%D' should be initialized in the member initialization list", member); + } + + perform_member_init (member, name, init, from_init_list); + mem_init_list = TREE_CHAIN (mem_init_list); + } + + /* Now initialize any members from our bases. */ + while (mem_init_list) + { + tree name, init, field; + + if (TREE_PURPOSE (mem_init_list)) + { + name = TREE_PURPOSE (mem_init_list); + init = TREE_VALUE (mem_init_list); + /* XXX: this may need the COMPONENT_REF operand 0 check if + it turns out we actually get them. */ + field = IDENTIFIER_CLASS_VALUE (name); + + /* If one member shadows another, get the outermost one. */ + if (TREE_CODE (field) == TREE_LIST) + { + field = TREE_VALUE (field); + if (decl_type_context (field) != current_class_type) + cp_error ("field `%D' not in immediate context", field); + } + +#if 0 + /* It turns out if you have an anonymous union in the + class, a member from it can end up not being on the + list of fields (rather, the type is), and therefore + won't be seen by the for loop above. */ + + /* The code in this for loop is derived from a general loop + which had this check in it. Theoretically, we've hit + every initialization for the list of members in T, so + we shouldn't have anything but these left in this list. */ + my_friendly_assert (DECL_FIELD_CONTEXT (field) != t, 351); +#endif + + perform_member_init (field, name, init, 1); + } + mem_init_list = TREE_CHAIN (mem_init_list); + } + + if (! immediately) + { + do_pending_stack_adjust (); + my_friendly_assert (base_init_expr == 0, 207); + base_init_expr = expr; + TREE_TYPE (expr) = void_type_node; + RTL_EXPR_RTL (expr) = const0_rtx; + RTL_EXPR_SEQUENCE (expr) = get_insns (); + rtl_expr_chain = tree_cons (NULL_TREE, expr, rtl_expr_chain); + end_sequence (); + TREE_SIDE_EFFECTS (expr) = 1; + } + + /* All the implicit try blocks we built up will be zapped + when we come to a real binding contour boundary. */ +} + +/* Check that all fields are properly initialized after + an assignment to `this'. */ + +void +check_base_init (t) + tree t; +{ + tree member; + for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) + if (DECL_NAME (member) && TREE_USED (member)) + cp_error ("field `%D' used before initialized (after assignment to `this')", + member); +} + +/* This code sets up the virtual function tables appropriate for + the pointer DECL. It is a one-ply initialization. + + BINFO is the exact type that DECL is supposed to be. In + multiple inheritance, this might mean "C's A" if C : A, B. */ + +static void +expand_virtual_init (binfo, decl) + tree binfo, decl; +{ + tree type = BINFO_TYPE (binfo); + tree vtbl, vtbl_ptr; + tree vtype, vtype_binfo; + + /* This code is crusty. Should be simple, like: + vtbl = BINFO_VTABLE (binfo); + */ + vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type)); + vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0); + vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo)); + assemble_external (vtbl); + TREE_USED (vtbl) = 1; + vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl); + decl = convert_pointer_to_real (vtype_binfo, decl); + vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype); + if (vtbl_ptr == error_mark_node) + return; + + /* Have to convert VTBL since array sizes may be different. */ + vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); + expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl)); +} + +/* If an exception is thrown in a constructor, those base classes already + constructed must be destroyed. This function creates the cleanup + for BINFO, which has just been constructed. If FLAG is non-NULL, + it is a DECL which is non-zero when this base needs to be + destroyed. */ + +static void +expand_cleanup_for_base (binfo, vlist, flag) + tree binfo; + tree vlist; + tree flag; +{ + tree expr; + + if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo))) + { + /* All cleanups must be on the function_obstack. */ + push_obstacks_nochange (); + resume_temporary_allocation (); + + /* Call the destructor. */ + expr = build_base_dtor_call (current_class_ref, binfo, + integer_zero_node); + if (flag) + expr = fold (build (COND_EXPR, void_type_node, + truthvalue_conversion (flag), + expr, integer_zero_node)); + + pop_obstacks (); + add_partial_entry (expr); + } + + if (TYPE_USES_PVBASES (BINFO_TYPE (binfo))) + { + /* Increment vlist by number of base's vbase classes. */ + expr = build_int_2 (pvbasecount (BINFO_TYPE (binfo), 0), 0); + expr = build_binary_op (PLUS_EXPR, vlist, expr); + expr = build_modify_expr (vlist, NOP_EXPR, expr); + expand_expr_stmt (expr); + } +} + +/* Subroutine of `expand_aggr_vbase_init'. + BINFO is the binfo of the type that is being initialized. + INIT_LIST is the list of initializers for the virtual baseclass. */ + +static void +expand_aggr_vbase_init_1 (binfo, exp, addr, init_list) + tree binfo, exp, addr, init_list; +{ + tree init = purpose_member (binfo, init_list); + tree ref = build_indirect_ref (addr, NULL_PTR); + + expand_start_target_temps (); + + if (init) + init = TREE_VALUE (init); + /* Call constructors, but don't set up vtables. */ + expand_aggr_init_1 (binfo, exp, ref, init, LOOKUP_COMPLAIN); + + expand_end_target_temps (); + free_temp_slots (); +} + +/* Construct the virtual base-classes of THIS_REF (whose address is + THIS_PTR). The object has the indicated TYPE. The construction + actually takes place only if FLAG is non-zero. INIT_LIST is list + of initialization for constructor to perform. */ + +static void +construct_virtual_bases (type, this_ref, this_ptr, init_list, flag) + tree type; + tree this_ref; + tree this_ptr; + tree init_list; + tree flag; +{ + tree vbases; + tree result; + tree vlist = NULL_TREE; + + /* If there are no virtual baseclasses, we shouldn't even be here. */ + my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621); + + /* First set the pointers in our object that tell us where to find + our virtual baseclasses. */ + expand_start_cond (flag, 0); + if (TYPE_USES_PVBASES (type)) + { + init_vlist (type); + vlist = lookup_name (vlist_identifier, 0); + } + result = init_vbase_pointers (type, this_ptr); + if (result) + expand_expr_stmt (build_compound_expr (result)); + expand_end_cond (); + + /* Now, run through the baseclasses, initializing each. */ + for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; + vbases = TREE_CHAIN (vbases)) + { + tree tmp = purpose_member (vbases, result); + + /* If there are virtual base classes with destructors, we need to + emit cleanups to destroy them if an exception is thrown during + the construction process. These exception regions (i.e., the + period during which the cleanups must occur) begin from the time + the construction is complete to the end of the function. If we + create a conditional block in which to initialize the + base-classes, then the cleanup region for the virtual base begins + inside a block, and ends outside of that block. This situation + confuses the sjlj exception-handling code. Therefore, we do not + create a single conditional block, but one for each + initialization. (That way the cleanup regions always begin + in the outer block.) We trust the back-end to figure out + that the FLAG will not change across initializations, and + avoid doing multiple tests. */ + expand_start_cond (flag, 0); + expand_aggr_vbase_init_1 (vbases, this_ref, + TREE_OPERAND (TREE_VALUE (tmp), 0), + init_list); + expand_end_cond (); + + expand_cleanup_for_base (vbases, vlist, flag); + } +} + +/* Find the context in which this FIELD can be initialized. */ + +static tree +initializing_context (field) + tree field; +{ + tree t = DECL_CONTEXT (field); + + /* Anonymous union members can be initialized in the first enclosing + non-anonymous union context. */ + while (t && ANON_UNION_TYPE_P (t)) + t = TYPE_CONTEXT (t); + return t; +} + +/* Function to give error message if member initialization specification + is erroneous. FIELD is the member we decided to initialize. + TYPE is the type for which the initialization is being performed. + FIELD must be a member of TYPE. + + MEMBER_NAME is the name of the member. */ + +static int +member_init_ok_or_else (field, type, member_name) + tree field; + tree type; + const char *member_name; +{ + if (field == error_mark_node) + return 0; + if (field == NULL_TREE || initializing_context (field) != type) + { + cp_error ("class `%T' does not have any field named `%s'", type, + member_name); + return 0; + } + if (TREE_STATIC (field)) + { + cp_error ("field `%#D' is static; only point of initialization is its declaration", + field); + return 0; + } + + return 1; +} + +/* If NAME is a viable field name for the aggregate DECL, + and PARMS is a viable parameter list, then expand an _EXPR + which describes this initialization. + + Note that we do not need to chase through the class's base classes + to look for NAME, because if it's in that list, it will be handled + by the constructor for that base class. + + We do not yet have a fixed-point finder to instantiate types + being fed to overloaded constructors. If there is a unique + constructor, then argument types can be got from that one. + + If INIT is non-NULL, then it the initialization should + be placed in `current_base_init_list', where it will be processed + by `emit_base_init'. */ + +void +expand_member_init (exp, name, init) + tree exp, name, init; +{ + tree basetype = NULL_TREE, field; + tree type; + + if (exp == NULL_TREE) + return; /* complain about this later */ + + type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); + + if (name && TREE_CODE (name) == TYPE_DECL) + { + basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name)); + name = DECL_NAME (name); + } + + if (name == NULL_TREE && IS_AGGR_TYPE (type)) + switch (CLASSTYPE_N_BASECLASSES (type)) + { + case 0: + error ("base class initializer specified, but no base class to initialize"); + return; + case 1: + basetype = TYPE_BINFO_BASETYPE (type, 0); + break; + default: + error ("initializer for unnamed base class ambiguous"); + cp_error ("(type `%T' uses multiple inheritance)", type); + return; + } + + my_friendly_assert (init != NULL_TREE, 0); + + /* The grammar should not allow fields which have names that are + TYPENAMEs. Therefore, if the field has a non-NULL TREE_TYPE, we + may assume that this is an attempt to initialize a base class + member of the current type. Otherwise, it is an attempt to + initialize a member field. */ + + if (init == void_type_node) + init = NULL_TREE; + + if (name == NULL_TREE || basetype) + { + tree base_init; + + if (name == NULL_TREE) + { +#if 0 + if (basetype) + name = TYPE_IDENTIFIER (basetype); + else + { + error ("no base class to initialize"); + return; + } +#endif + } + else if (basetype != type + && ! current_template_parms + && ! vec_binfo_member (basetype, + TYPE_BINFO_BASETYPES (type)) + && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type))) + { + if (IDENTIFIER_CLASS_VALUE (name)) + goto try_member; + if (TYPE_USES_VIRTUAL_BASECLASSES (type)) + cp_error ("type `%T' is not an immediate or virtual basetype for `%T'", + basetype, type); + else + cp_error ("type `%T' is not an immediate basetype for `%T'", + basetype, type); + return; + } + + if (purpose_member (basetype, current_base_init_list)) + { + cp_error ("base class `%T' already initialized", basetype); + return; + } + + if (warn_reorder && current_member_init_list) + { + cp_warning ("base initializer for `%T'", basetype); + warning (" will be re-ordered to precede member initializations"); + } + + base_init = build_tree_list (basetype, init); + current_base_init_list = chainon (current_base_init_list, base_init); + } + else + { + tree member_init; + + try_member: + field = lookup_field (type, name, 1, 0); + + if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name))) + return; + + if (purpose_member (name, current_member_init_list)) + { + cp_error ("field `%D' already initialized", field); + return; + } + + member_init = build_tree_list (name, init); + current_member_init_list = chainon (current_member_init_list, member_init); + } +} + +/* This is like `expand_member_init', only it stores one aggregate + value into another. + + INIT comes in two flavors: it is either a value which + is to be stored in EXP, or it is a parameter list + to go to a constructor, which will operate on EXP. + If INIT is not a parameter list for a constructor, then set + LOOKUP_ONLYCONVERTING. + If FLAGS is LOOKUP_ONLYCONVERTING then it is the = init form of + the initializer, if FLAGS is 0, then it is the (init) form. + If `init' is a CONSTRUCTOR, then we emit a warning message, + explaining that such initializations are invalid. + + ALIAS_THIS is nonzero iff we are initializing something which is + essentially an alias for current_class_ref. In this case, the base + constructor may move it on us, and we must keep track of such + deviations. + + If INIT resolves to a CALL_EXPR which happens to return + something of the type we are looking for, then we know + that we can safely use that call to perform the + initialization. + + The virtual function table pointer cannot be set up here, because + we do not really know its type. + + Virtual baseclass pointers are also set up here. + + This never calls operator=(). + + When initializing, nothing is CONST. + + A default copy constructor may have to be used to perform the + initialization. + + A constructor or a conversion operator may have to be used to + perform the initialization, but not both, as it would be ambiguous. */ + +void +expand_aggr_init (exp, init, flags) + tree exp, init; + int flags; +{ + tree type = TREE_TYPE (exp); + int was_const = TREE_READONLY (exp); + int was_volatile = TREE_THIS_VOLATILE (exp); + + if (init == error_mark_node) + return; + + TREE_READONLY (exp) = 0; + TREE_THIS_VOLATILE (exp) = 0; + + if (init && TREE_CODE (init) != TREE_LIST) + flags |= LOOKUP_ONLYCONVERTING; + + if (TREE_CODE (type) == ARRAY_TYPE) + { + /* Must arrange to initialize each element of EXP + from elements of INIT. */ + tree itype = init ? TREE_TYPE (init) : NULL_TREE; + if (CP_TYPE_QUALS (type) != TYPE_UNQUALIFIED) + { + TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); + if (init) + TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype); + } + if (init && TREE_TYPE (init) == NULL_TREE) + { + /* Handle bad initializers like: + class COMPLEX { + public: + double re, im; + COMPLEX(double r = 0.0, double i = 0.0) {re = r; im = i;}; + ~COMPLEX() {}; + }; + + int main(int argc, char **argv) { + COMPLEX zees(1.0, 0.0)[10]; + } + */ + error ("bad array initializer"); + return; + } + expand_vec_init (exp, exp, array_type_nelts (type), init, + init && same_type_p (TREE_TYPE (init), + TREE_TYPE (exp))); + TREE_READONLY (exp) = was_const; + TREE_THIS_VOLATILE (exp) = was_volatile; + TREE_TYPE (exp) = type; + if (init) + TREE_TYPE (init) = itype; + return; + } + + if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL) + /* just know that we've seen something for this node */ + TREE_USED (exp) = 1; + +#if 0 + /* If initializing from a GNU C CONSTRUCTOR, consider the elts in the + constructor as parameters to an implicit GNU C++ constructor. */ + if (init && TREE_CODE (init) == CONSTRUCTOR + && TYPE_HAS_CONSTRUCTOR (type) + && TREE_TYPE (init) == type) + init = CONSTRUCTOR_ELTS (init); +#endif + + TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); + expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, + init, LOOKUP_NORMAL|flags); + TREE_TYPE (exp) = type; + TREE_READONLY (exp) = was_const; + TREE_THIS_VOLATILE (exp) = was_volatile; +} + +static tree +no_vlist_base_init (rval, exp, init, binfo, flags) + tree rval, exp, init, binfo; + int flags; +{ + tree nrval, func, parms; + + /* Obtain the vlist-expecting ctor. */ + func = rval; + my_friendly_assert (TREE_CODE (func) == CALL_EXPR, 20000131); + func = TREE_OPERAND (func, 0); + my_friendly_assert (TREE_CODE (func) == ADDR_EXPR, 20000132); + + if (init == NULL_TREE + || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init))) + { + parms = init; + if (parms) + init = TREE_VALUE (parms); + } + else + parms = build_expr_list (NULL_TREE, init); + + flags &= ~LOOKUP_HAS_VLIST; + + parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms); + flags |= LOOKUP_HAS_IN_CHARGE; + + nrval = build_method_call (exp, ctor_identifier, + parms, binfo, flags); + + func = build (NE_EXPR, boolean_type_node, + func, null_pointer_node); + nrval = build (COND_EXPR, void_type_node, + func, rval, nrval); + return nrval; +} + +static void +expand_default_init (binfo, true_exp, exp, init, flags) + tree binfo; + tree true_exp, exp; + tree init; + int flags; +{ + tree type = TREE_TYPE (exp); + + /* It fails because there may not be a constructor which takes + its own type as the first (or only parameter), but which does + take other types via a conversion. So, if the thing initializing + the expression is a unit element of type X, first try X(X&), + followed by initialization by X. If neither of these work + out, then look hard. */ + tree rval; + tree parms; + tree vlist = NULL_TREE; + tree orig_init = init; + + if (init && TREE_CODE (init) != TREE_LIST + && (flags & LOOKUP_ONLYCONVERTING)) + { + /* Base subobjects should only get direct-initialization. */ + if (true_exp != exp) + abort (); + + if (flags & DIRECT_BIND) + /* Do nothing. We hit this in two cases: Reference initialization, + where we aren't initializing a real variable, so we don't want + to run a new constructor; and catching an exception, where we + have already built up the constructor call so we could wrap it + in an exception region. */; + else + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + + if (TREE_CODE (init) == TRY_CATCH_EXPR) + /* We need to protect the initialization of a catch parm + with a call to terminate(), which shows up as a TRY_CATCH_EXPR + around the TARGET_EXPR for the copy constructor. See + expand_start_catch_block. */ + TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp, + TREE_OPERAND (init, 0)); + else + init = build (INIT_EXPR, TREE_TYPE (exp), exp, init); + TREE_SIDE_EFFECTS (init) = 1; + expand_expr_stmt (init); + return; + } + + if (init == NULL_TREE + || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init))) + { + parms = init; + if (parms) + init = TREE_VALUE (parms); + } + else + parms = build_expr_list (NULL_TREE, init); + + if (TYPE_USES_VIRTUAL_BASECLASSES (type)) + { + if (TYPE_USES_PVBASES (type)) + { + /* In compatibility mode, when not calling a base ctor, + we do not pass the vlist argument. */ + if (true_exp == exp) + vlist = flag_vtable_thunks_compat? NULL_TREE : vlist_zero_node; + else + vlist = lookup_name (vlist_identifier, 0); + + if (vlist) + { + parms = expr_tree_cons (NULL_TREE, vlist, parms); + flags |= LOOKUP_HAS_VLIST; + } + } + if (true_exp == exp) + parms = expr_tree_cons (NULL_TREE, integer_one_node, parms); + else + parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms); + flags |= LOOKUP_HAS_IN_CHARGE; + } + + rval = build_method_call (exp, ctor_identifier, + parms, binfo, flags); + if (vlist && true_exp != exp && flag_vtable_thunks_compat) + { + rval = no_vlist_base_init (rval, exp, orig_init, binfo, flags); + } + if (TREE_SIDE_EFFECTS (rval)) + expand_expr_stmt (rval); +} + +/* This function is responsible for initializing EXP with INIT + (if any). + + BINFO is the binfo of the type for who we are performing the + initialization. For example, if W is a virtual base class of A and B, + and C : A, B. + If we are initializing B, then W must contain B's W vtable, whereas + were we initializing C, W must contain C's W vtable. + + TRUE_EXP is nonzero if it is the true expression being initialized. + In this case, it may be EXP, or may just contain EXP. The reason we + need this is because if EXP is a base element of TRUE_EXP, we + don't necessarily know by looking at EXP where its virtual + baseclass fields should really be pointing. But we do know + from TRUE_EXP. In constructors, we don't know anything about + the value being initialized. + + ALIAS_THIS serves the same purpose it serves for expand_aggr_init. + + FLAGS is just passes to `build_method_call'. See that function for + its description. */ + +static void +expand_aggr_init_1 (binfo, true_exp, exp, init, flags) + tree binfo; + tree true_exp, exp; + tree init; + int flags; +{ + tree type = TREE_TYPE (exp); + + my_friendly_assert (init != error_mark_node && type != error_mark_node, 211); + + /* Use a function returning the desired type to initialize EXP for us. + If the function is a constructor, and its first argument is + NULL_TREE, know that it was meant for us--just slide exp on + in and expand the constructor. Constructors now come + as TARGET_EXPRs. */ + + if (init && TREE_CODE (exp) == VAR_DECL + && TREE_CODE (init) == CONSTRUCTOR + && TREE_HAS_CONSTRUCTOR (init)) + { + tree t = store_init_value (exp, init); + if (!t) + { + expand_decl_init (exp); + return; + } + t = build (INIT_EXPR, type, exp, init); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr_stmt (t); + return; + } + + /* We know that expand_default_init can handle everything we want + at this point. */ + expand_default_init (binfo, true_exp, exp, init, flags); +} + +/* Report an error if NAME is not the name of a user-defined, + aggregate type. If OR_ELSE is nonzero, give an error message. */ + +int +is_aggr_typedef (name, or_else) + tree name; + int or_else; +{ + tree type; + + if (name == error_mark_node) + return 0; + + if (IDENTIFIER_HAS_TYPE_VALUE (name)) + type = IDENTIFIER_TYPE_VALUE (name); + else + { + if (or_else) + cp_error ("`%T' is not an aggregate typedef", name); + return 0; + } + + if (! IS_AGGR_TYPE (type) + && TREE_CODE (type) != TEMPLATE_TYPE_PARM + && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM) + { + if (or_else) + cp_error ("`%T' is not an aggregate type", type); + return 0; + } + return 1; +} + +/* Report an error if TYPE is not a user-defined, aggregate type. If + OR_ELSE is nonzero, give an error message. */ + +int +is_aggr_type (type, or_else) + tree type; + int or_else; +{ + if (type == error_mark_node) + return 0; + + if (! IS_AGGR_TYPE (type) + && TREE_CODE (type) != TEMPLATE_TYPE_PARM + && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM) + { + if (or_else) + cp_error ("`%T' is not an aggregate type", type); + return 0; + } + return 1; +} + +/* Like is_aggr_typedef, but returns typedef if successful. */ + +tree +get_aggr_from_typedef (name, or_else) + tree name; + int or_else; +{ + tree type; + + if (name == error_mark_node) + return NULL_TREE; + + if (IDENTIFIER_HAS_TYPE_VALUE (name)) + type = IDENTIFIER_TYPE_VALUE (name); + else + { + if (or_else) + cp_error ("`%T' fails to be an aggregate typedef", name); + return NULL_TREE; + } + + if (! IS_AGGR_TYPE (type) + && TREE_CODE (type) != TEMPLATE_TYPE_PARM + && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM) + { + if (or_else) + cp_error ("type `%T' is of non-aggregate type", type); + return NULL_TREE; + } + return type; +} + +tree +get_type_value (name) + tree name; +{ + if (name == error_mark_node) + return NULL_TREE; + + if (IDENTIFIER_HAS_TYPE_VALUE (name)) + return IDENTIFIER_TYPE_VALUE (name); + else + return NULL_TREE; +} + + +/* This code could just as well go in `class.c', but is placed here for + modularity. */ + +/* For an expression of the form TYPE :: NAME (PARMLIST), build + the appropriate function call. */ + +tree +build_member_call (type, name, parmlist) + tree type, name, parmlist; +{ + tree t; + tree method_name; + int dtor = 0; + tree basetype_path, decl; + + if (TREE_CODE (name) == TEMPLATE_ID_EXPR + && TREE_CODE (type) == NAMESPACE_DECL) + { + /* 'name' already refers to the decls from the namespace, since we + hit do_identifier for template_ids. */ + method_name = TREE_OPERAND (name, 0); + /* FIXME: Since we don't do independent names right yet, the + name might also be a LOOKUP_EXPR. Once we resolve this to a + real decl earlier, this can go. This may happen during + tsubst'ing. */ + if (TREE_CODE (method_name) == LOOKUP_EXPR) + { + method_name = lookup_namespace_name + (type, TREE_OPERAND (method_name, 0)); + TREE_OPERAND (name, 0) = method_name; + } + my_friendly_assert (is_overloaded_fn (method_name), 980519); + return build_x_function_call (name, parmlist, current_class_ref); + } + + if (type == std_node) + return build_x_function_call (do_scoped_id (name, 0), parmlist, + current_class_ref); + if (TREE_CODE (type) == NAMESPACE_DECL) + return build_x_function_call (lookup_namespace_name (type, name), + parmlist, current_class_ref); + + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + method_name = TREE_OPERAND (name, 0); + if (TREE_CODE (method_name) == COMPONENT_REF) + method_name = TREE_OPERAND (method_name, 1); + if (is_overloaded_fn (method_name)) + method_name = DECL_NAME (OVL_CURRENT (method_name)); + TREE_OPERAND (name, 0) = method_name; + } + else + method_name = name; + + if (TREE_CODE (method_name) == BIT_NOT_EXPR) + { + method_name = TREE_OPERAND (method_name, 0); + dtor = 1; + } + + /* This shouldn't be here, and build_member_call shouldn't appear in + parse.y! (mrs) */ + if (type && TREE_CODE (type) == IDENTIFIER_NODE + && get_aggr_from_typedef (type, 0) == 0) + { + tree ns = lookup_name (type, 0); + if (ns && TREE_CODE (ns) == NAMESPACE_DECL) + { + return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref); + } + } + + if (type == NULL_TREE || ! is_aggr_type (type, 1)) + return error_mark_node; + + /* An operator we did not like. */ + if (name == NULL_TREE) + return error_mark_node; + + if (dtor) + { + cp_error ("cannot call destructor `%T::~%T' without object", type, + method_name); + return error_mark_node; + } + + decl = maybe_dummy_object (type, &basetype_path); + + /* Convert 'this' to the specified type to disambiguate conversion + to the function's context. Apparently Standard C++ says that we + shouldn't do this. */ + if (decl == current_class_ref + && ! pedantic + && ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type)) + { + tree olddecl = current_class_ptr; + tree oldtype = TREE_TYPE (TREE_TYPE (olddecl)); + if (oldtype != type) + { + tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype)); + decl = convert_force (build_pointer_type (newtype), olddecl, 0); + decl = build_indirect_ref (decl, NULL_PTR); + } + } + + if (method_name == constructor_name (type) + || method_name == constructor_name_full (type)) + return build_functional_cast (type, parmlist); + if (lookup_fnfields (basetype_path, method_name, 0)) + return build_method_call (decl, + TREE_CODE (name) == TEMPLATE_ID_EXPR + ? name : method_name, + parmlist, basetype_path, + LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); + if (TREE_CODE (name) == IDENTIFIER_NODE + && ((t = lookup_field (TYPE_BINFO (type), name, 1, 0)))) + { + if (t == error_mark_node) + return error_mark_node; + if (TREE_CODE (t) == FIELD_DECL) + { + if (is_dummy_object (decl)) + { + cp_error ("invalid use of non-static field `%D'", t); + return error_mark_node; + } + decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t); + } + else if (TREE_CODE (t) == VAR_DECL) + decl = t; + else + { + cp_error ("invalid use of member `%D'", t); + return error_mark_node; + } + if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl))) + return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, + parmlist, NULL_TREE); + return build_function_call (decl, parmlist); + } + else + { + cp_error ("no method `%T::%D'", type, name); + return error_mark_node; + } +} + +/* Build a reference to a member of an aggregate. This is not a + C++ `&', but really something which can have its address taken, + and then act as a pointer to member, for example TYPE :: FIELD + can have its address taken by saying & TYPE :: FIELD. + + @@ Prints out lousy diagnostics for operator + @@ fields. + + @@ This function should be rewritten and placed in search.c. */ + +tree +build_offset_ref (type, name) + tree type, name; +{ + tree decl, t = error_mark_node; + tree member; + tree basebinfo = NULL_TREE; + tree orig_name = name; + + /* class templates can come in as TEMPLATE_DECLs here. */ + if (TREE_CODE (name) == TEMPLATE_DECL) + return name; + + if (type == std_node) + return do_scoped_id (name, 0); + + if (processing_template_decl || uses_template_parms (type)) + return build_min_nt (SCOPE_REF, type, name); + + /* Handle namespace names fully here. */ + if (TREE_CODE (type) == NAMESPACE_DECL) + { + t = lookup_namespace_name (type, name); + if (t != error_mark_node && ! type_unknown_p (t)) + { + mark_used (t); + t = convert_from_reference (t); + } + return t; + } + + if (type == NULL_TREE || ! is_aggr_type (type, 1)) + return error_mark_node; + + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + /* If the NAME is a TEMPLATE_ID_EXPR, we are looking at + something like `a.template f' or the like. For the most + part, we treat this just like a.f. We do remember, however, + the template-id that was used. */ + name = TREE_OPERAND (orig_name, 0); + + if (TREE_CODE (name) == LOOKUP_EXPR) + /* This can happen during tsubst'ing. */ + name = TREE_OPERAND (name, 0); + + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0); + } + + if (TREE_CODE (name) == BIT_NOT_EXPR) + { + if (! check_dtor_name (type, name)) + cp_error ("qualified type `%T' does not match destructor name `~%T'", + type, TREE_OPERAND (name, 0)); + name = dtor_identifier; + } +#if 0 + /* I think this is wrong, but the draft is unclear. --jason 6/15/98 */ + else if (name == constructor_name_full (type) + || name == constructor_name (type)) + name = ctor_identifier; +#endif + + if (TYPE_SIZE (complete_type (type)) == 0 + && !TYPE_BEING_DEFINED (type)) + { + cp_error ("incomplete type `%T' does not have member `%D'", type, + name); + return error_mark_node; + } + + decl = maybe_dummy_object (type, &basebinfo); + + member = lookup_member (basebinfo, name, 1, 0); + + if (member == error_mark_node) + return error_mark_node; + + /* A lot of this logic is now handled in lookup_field and + lookup_fnfield. */ + if (member && BASELINK_P (member)) + { + /* Go from the TREE_BASELINK to the member function info. */ + tree fnfields = member; + t = TREE_VALUE (fnfields); + + if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR) + { + /* The FNFIELDS are going to contain functions that aren't + necessarily templates, and templates that don't + necessarily match the explicit template parameters. We + save all the functions, and the explicit parameters, and + then figure out exactly what to instantiate with what + arguments in instantiate_type. */ + + if (TREE_CODE (t) != OVERLOAD) + /* The code in instantiate_type which will process this + expects to encounter OVERLOADs, not raw functions. */ + t = ovl_cons (t, NULL_TREE); + + return build (OFFSET_REF, + unknown_type_node, + decl, + build (TEMPLATE_ID_EXPR, + TREE_TYPE (t), + t, + TREE_OPERAND (orig_name, 1))); + } + + if (!really_overloaded_fn (t)) + { + /* Get rid of a potential OVERLOAD around it */ + t = OVL_CURRENT (t); + + /* unique functions are handled easily. */ + basebinfo = TREE_PURPOSE (fnfields); + if (!enforce_access (basebinfo, t)) + return error_mark_node; + mark_used (t); + if (DECL_STATIC_FUNCTION_P (t)) + return t; + return build (OFFSET_REF, TREE_TYPE (t), decl, t); + } + + /* FNFIELDS is most likely allocated on the search_obstack, + which will go away after this class scope. If we need + to save this value for later (i.e. for use as an initializer + for a static variable), then do so here. + + ??? The smart thing to do for the case of saving initializers + is to resolve them before we're done with this scope. */ + if (!TREE_PERMANENT (fnfields) + && ! allocation_temporary_p ()) + fnfields = copy_list (fnfields); + + TREE_TYPE (fnfields) = unknown_type_node; + return build (OFFSET_REF, unknown_type_node, decl, fnfields); + } + + t = member; + + if (t == NULL_TREE) + { + cp_error ("`%D' is not a member of type `%T'", name, type); + return error_mark_node; + } + + if (TREE_CODE (t) == TYPE_DECL) + { + TREE_USED (t) = 1; + return t; + } + /* static class members and class-specific enum + values can be returned without further ado. */ + if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL) + { + mark_used (t); + return convert_from_reference (t); + } + + if (TREE_CODE (t) == FIELD_DECL && DECL_C_BIT_FIELD (t)) + { + cp_error ("illegal pointer to bit field `%D'", t); + return error_mark_node; + } + + /* static class functions too. */ + if (TREE_CODE (t) == FUNCTION_DECL + && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) + my_friendly_abort (53); + + /* In member functions, the form `type::name' is no longer + equivalent to `this->type::name', at least not until + resolve_offset_ref. */ + return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t); +} + +/* If a OFFSET_REF made it through to here, then it did + not have its address taken. */ + +tree +resolve_offset_ref (exp) + tree exp; +{ + tree type = TREE_TYPE (exp); + tree base = NULL_TREE; + tree member; + tree basetype, addr; + + if (TREE_CODE (exp) == OFFSET_REF) + { + member = TREE_OPERAND (exp, 1); + base = TREE_OPERAND (exp, 0); + } + else + { + my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214); + if (TYPE_OFFSET_BASETYPE (type) != current_class_type) + { + error ("object missing in use of pointer-to-member construct"); + return error_mark_node; + } + member = exp; + type = TREE_TYPE (type); + base = current_class_ref; + } + + if (BASELINK_P (member)) + { + cp_pedwarn ("assuming & on overloaded member function"); + return build_unary_op (ADDR_EXPR, exp, 0); + } + + if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE) + { + cp_pedwarn ("assuming & on `%E'", member); + return build_unary_op (ADDR_EXPR, exp, 0); + } + + if ((TREE_CODE (member) == VAR_DECL + && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member)) + && ! TYPE_PTRMEM_P (TREE_TYPE (member))) + || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE) + { + /* These were static members. */ + if (mark_addressable (member) == 0) + return error_mark_node; + return member; + } + + if (TREE_CODE (TREE_TYPE (member)) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE) + return member; + + /* Syntax error can cause a member which should + have been seen as static to be grok'd as non-static. */ + if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE) + { + if (TREE_ADDRESSABLE (member) == 0) + { + cp_error_at ("member `%D' is non-static but referenced as a static member", + member); + error ("at this point in file"); + TREE_ADDRESSABLE (member) = 1; + } + return error_mark_node; + } + + /* The first case is really just a reference to a member of `this'. */ + if (TREE_CODE (member) == FIELD_DECL + && (base == current_class_ref || is_dummy_object (base))) + { + tree basetype_path; + tree expr; + + if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE) + basetype = TYPE_OFFSET_BASETYPE (type); + else + basetype = DECL_CONTEXT (member); + + base = current_class_ptr; + + if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0) + { + error_not_base_type (basetype, TREE_TYPE (TREE_TYPE (base))); + return error_mark_node; + } + /* Kludge: we need to use basetype_path now, because + convert_pointer_to will bash it. */ + enforce_access (basetype_path, member); + addr = convert_pointer_to (basetype, base); + + /* Even in the case of illegal access, we form the + COMPONENT_REF; that will allow better error recovery than + just feeding back error_mark_node. */ + expr = build (COMPONENT_REF, TREE_TYPE (member), + build_indirect_ref (addr, NULL_PTR), member); + return convert_from_reference (expr); + } + + /* Ensure that we have an object. */ + if (is_dummy_object (base)) + addr = error_mark_node; + else + /* If this is a reference to a member function, then return the + address of the member function (which may involve going + through the object's vtable), otherwise, return an expression + for the dereferenced pointer-to-member construct. */ + addr = build_unary_op (ADDR_EXPR, base, 0); + + if (TYPE_PTRMEM_P (TREE_TYPE (member))) + { + if (addr == error_mark_node) + { + cp_error ("object missing in `%E'", exp); + return error_mark_node; + } + + basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member))); + addr = convert_pointer_to (basetype, addr); + member = cp_convert (ptrdiff_type_node, member); + + /* Pointer to data members are offset by one, so that a null + pointer with a real value of 0 is distinguishable from an + offset of the first member of a structure. */ + member = build_binary_op (MINUS_EXPR, member, + cp_convert (ptrdiff_type_node, integer_one_node)); + + return build1 (INDIRECT_REF, type, + build (PLUS_EXPR, build_pointer_type (type), + addr, member)); + } + else if (TYPE_PTRMEMFUNC_P (TREE_TYPE (member))) + { + return get_member_function_from_ptrfunc (&addr, member); + } + my_friendly_abort (56); + /* NOTREACHED */ + return NULL_TREE; +} + +/* Return either DECL or its known constant value (if it has one). */ + +tree +decl_constant_value (decl) + tree decl; +{ + if (! TREE_THIS_VOLATILE (decl) + && DECL_INITIAL (decl) + && DECL_INITIAL (decl) != error_mark_node + /* This is invalid if initial value is not constant. + If it has either a function call, a memory reference, + or a variable, then re-evaluating it could give different results. */ + && TREE_CONSTANT (DECL_INITIAL (decl)) + /* Check for cases where this is sub-optimal, even though valid. */ + && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR) + return DECL_INITIAL (decl); + return decl; +} + +/* Common subroutines of build_new and build_vec_delete. */ + +/* Call the global __builtin_delete to delete ADDR. */ + +static tree +build_builtin_delete_call (addr) + tree addr; +{ + mark_used (global_delete_fndecl); + return build_call (global_delete_fndecl, + void_type_node, build_expr_list (NULL_TREE, addr)); +} + +/* Generate a C++ "new" expression. DECL is either a TREE_LIST + (which needs to go through some sort of groktypename) or it + is the name of the class we are newing. INIT is an initialization value. + It is either an EXPRLIST, an EXPR_NO_COMMAS, or something in braces. + If INIT is void_type_node, it means do *not* call a constructor + for this instance. + + For types with constructors, the data returned is initialized + by the appropriate constructor. + + Whether the type has a constructor or not, if it has a pointer + to a virtual function table, then that pointer is set up + here. + + Unless I am mistaken, a call to new () will return initialized + data regardless of whether the constructor itself is private or + not. NOPE; new fails if the constructor is private (jcm). + + Note that build_new does nothing to assure that any special + alignment requirements of the type are met. Rather, it leaves + it up to malloc to do the right thing. Otherwise, folding to + the right alignment cal cause problems if the user tries to later + free the memory returned by `new'. + + PLACEMENT is the `placement' list for user-defined operator new (). */ + +extern int flag_check_new; + +tree +build_new (placement, decl, init, use_global_new) + tree placement; + tree decl, init; + int use_global_new; +{ + tree type, rval; + tree nelts = NULL_TREE, t; + int has_array = 0; + + tree pending_sizes = NULL_TREE; + + if (decl == error_mark_node) + return error_mark_node; + + if (TREE_CODE (decl) == TREE_LIST) + { + tree absdcl = TREE_VALUE (decl); + tree last_absdcl = NULL_TREE; + int old_immediate_size_expand = 0; + + if (current_function_decl + && DECL_CONSTRUCTOR_P (current_function_decl)) + { + old_immediate_size_expand = immediate_size_expand; + immediate_size_expand = 0; + } + + nelts = integer_one_node; + + if (absdcl && TREE_CODE (absdcl) == CALL_EXPR) + my_friendly_abort (215); + while (absdcl && TREE_CODE (absdcl) == INDIRECT_REF) + { + last_absdcl = absdcl; + absdcl = TREE_OPERAND (absdcl, 0); + } + + if (absdcl && TREE_CODE (absdcl) == ARRAY_REF) + { + /* probably meant to be a vec new */ + tree this_nelts; + + while (TREE_OPERAND (absdcl, 0) + && TREE_CODE (TREE_OPERAND (absdcl, 0)) == ARRAY_REF) + { + last_absdcl = absdcl; + absdcl = TREE_OPERAND (absdcl, 0); + } + + has_array = 1; + this_nelts = TREE_OPERAND (absdcl, 1); + if (this_nelts != error_mark_node) + { + if (this_nelts == NULL_TREE) + error ("new of array type fails to specify size"); + else if (processing_template_decl) + { + nelts = this_nelts; + absdcl = TREE_OPERAND (absdcl, 0); + } + else + { + int flags = pedantic ? WANT_INT : (WANT_INT | WANT_ENUM); + if (build_expr_type_conversion (flags, this_nelts, 0) + == NULL_TREE) + pedwarn ("size in array new must have integral type"); + + this_nelts = save_expr (cp_convert (sizetype, this_nelts)); + absdcl = TREE_OPERAND (absdcl, 0); + if (this_nelts == integer_zero_node) + { + warning ("zero size array reserves no space"); + nelts = integer_zero_node; + } + else + nelts = build_binary_op (MULT_EXPR, nelts, this_nelts); + } + } + else + nelts = integer_zero_node; + } + + if (last_absdcl) + TREE_OPERAND (last_absdcl, 0) = absdcl; + else + TREE_VALUE (decl) = absdcl; + + type = groktypename (decl); + if (! type || type == error_mark_node) + { + immediate_size_expand = old_immediate_size_expand; + return error_mark_node; + } + + if (current_function_decl + && DECL_CONSTRUCTOR_P (current_function_decl)) + { + pending_sizes = get_pending_sizes (); + immediate_size_expand = old_immediate_size_expand; + } + } + else if (TREE_CODE (decl) == IDENTIFIER_NODE) + { + if (IDENTIFIER_HAS_TYPE_VALUE (decl)) + { + /* An aggregate type. */ + type = IDENTIFIER_TYPE_VALUE (decl); + decl = TYPE_MAIN_DECL (type); + } + else + { + /* A builtin type. */ + decl = lookup_name (decl, 1); + my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 215); + type = TREE_TYPE (decl); + } + } + else if (TREE_CODE (decl) == TYPE_DECL) + { + type = TREE_TYPE (decl); + } + else + { + type = decl; + decl = TYPE_MAIN_DECL (type); + } + + if (processing_template_decl) + { + if (has_array) + t = min_tree_cons (min_tree_cons (NULL_TREE, type, NULL_TREE), + build_min_nt (ARRAY_REF, NULL_TREE, nelts), + NULL_TREE); + else + t = type; + + rval = build_min_nt (NEW_EXPR, placement, t, init); + NEW_EXPR_USE_GLOBAL (rval) = use_global_new; + return rval; + } + + /* ``A reference cannot be created by the new operator. A reference + is not an object (8.2.2, 8.4.3), so a pointer to it could not be + returned by new.'' ARM 5.3.3 */ + if (TREE_CODE (type) == REFERENCE_TYPE) + { + error ("new cannot be applied to a reference type"); + type = TREE_TYPE (type); + } + + if (TREE_CODE (type) == FUNCTION_TYPE) + { + error ("new cannot be applied to a function type"); + return error_mark_node; + } + + /* When the object being created is an array, the new-expression yields a + pointer to the initial element (if any) of the array. For example, + both new int and new int[10] return an int*. 5.3.4. */ + if (TREE_CODE (type) == ARRAY_TYPE && has_array == 0) + { + nelts = array_type_nelts_top (type); + has_array = 1; + type = TREE_TYPE (type); + } + + if (has_array) + t = build_nt (ARRAY_REF, type, nelts); + else + t = type; + + rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init); + NEW_EXPR_USE_GLOBAL (rval) = use_global_new; + TREE_SIDE_EFFECTS (rval) = 1; + + /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */ + rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval); + TREE_NO_UNUSED_WARNING (rval) = 1; + + if (pending_sizes) + rval = build_compound_expr (chainon (pending_sizes, + build_expr_list (NULL_TREE, rval))); + + return rval; +} + +/* If non-NULL, a POINTER_TYPE equivalent to (java::lang::Class*). */ + +static tree jclass_node = NULL_TREE; + +/* Given a Java class, return a decl for the corresponding java.lang.Class. */ + +static tree +build_java_class_ref (type) + tree type; +{ + tree name, class_decl; + static tree CL_prefix = NULL_TREE; + if (CL_prefix == NULL_TREE) + CL_prefix = get_identifier("_CL_"); + if (jclass_node == NULL_TREE) + { + jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier("jclass")); + if (jclass_node == NULL_TREE) + fatal("call to Java constructor, while `jclass' undefined"); + jclass_node = TREE_TYPE (jclass_node); + } + name = build_overload_with_type (CL_prefix, type); + class_decl = IDENTIFIER_GLOBAL_VALUE (name); + if (class_decl == NULL_TREE) + { + push_obstacks_nochange (); + end_temporary_allocation (); + class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node)); + TREE_STATIC (class_decl) = 1; + DECL_EXTERNAL (class_decl) = 1; + TREE_PUBLIC (class_decl) = 1; + DECL_ARTIFICIAL (class_decl) = 1; + DECL_IGNORED_P (class_decl) = 1; + pushdecl_top_level (class_decl); + make_decl_rtl (class_decl, NULL_PTR, 1); + pop_obstacks (); + } + return class_decl; +} + +/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return + value is immediately handed to expand_expr. */ + +tree +build_new_1 (exp) + tree exp; +{ + tree placement, init; + tree type, true_type, size, rval; + tree nelts = NULL_TREE; + tree alloc_expr, alloc_node = NULL_TREE; + int has_array = 0; + enum tree_code code = NEW_EXPR; + int use_cookie, nothrow, check_new; + int use_global_new; + int use_java_new = 0; + + placement = TREE_OPERAND (exp, 0); + type = TREE_OPERAND (exp, 1); + init = TREE_OPERAND (exp, 2); + use_global_new = NEW_EXPR_USE_GLOBAL (exp); + + if (TREE_CODE (type) == ARRAY_REF) + { + has_array = 1; + nelts = TREE_OPERAND (type, 1); + type = TREE_OPERAND (type, 0); + } + true_type = type; + + if (CP_TYPE_QUALS (type)) + type = TYPE_MAIN_VARIANT (type); + + /* If our base type is an array, then make sure we know how many elements + it has. */ + while (TREE_CODE (true_type) == ARRAY_TYPE) + { + tree this_nelts = array_type_nelts_top (true_type); + nelts = build_binary_op (MULT_EXPR, nelts, this_nelts); + true_type = TREE_TYPE (true_type); + } + + if (!complete_type_or_else (true_type, exp)) + return error_mark_node; + + if (has_array) + size = fold (build_binary_op (MULT_EXPR, size_in_bytes (true_type), + nelts)); + else + size = size_in_bytes (type); + + if (TREE_CODE (true_type) == VOID_TYPE) + { + error ("invalid type `void' for new"); + return error_mark_node; + } + + if (TYPE_LANG_SPECIFIC (true_type) + && CLASSTYPE_ABSTRACT_VIRTUALS (true_type)) + { + abstract_virtuals_error (NULL_TREE, true_type); + return error_mark_node; + } + + if (TYPE_LANG_SPECIFIC (true_type) && IS_SIGNATURE (true_type)) + { + signature_error (NULL_TREE, true_type); + return error_mark_node; + } + + /* When we allocate an array, and the corresponding deallocation + function takes a second argument of type size_t, and that's the + "usual deallocation function", we allocate some extra space at + the beginning of the array to store the size of the array. + + Well, that's what we should do. For backwards compatibility, we + have to do this whenever there's a two-argument array-delete + operator. + + FIXME: For -fnew-abi, we don't have to maintain backwards + compatibility and we should fix this. */ + use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type) + && ! (placement && ! TREE_CHAIN (placement) + && TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node)); + + if (use_cookie) + { + tree extra = BI_header_size; + + size = size_binop (PLUS_EXPR, size, extra); + } + + if (has_array) + { + code = VEC_NEW_EXPR; + + if (init && pedantic) + cp_pedwarn ("initialization in array new"); + } + + /* Allocate the object. */ + + if (! has_array && ! placement && flag_this_is_variable > 0 + && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node) + { + if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) + rval = NULL_TREE; + else + { + error ("constructors take parameter lists"); + return error_mark_node; + } + } + else if (! placement && TYPE_FOR_JAVA (true_type)) + { + tree class_addr, alloc_decl; + tree class_decl = build_java_class_ref (true_type); + tree class_size = size_in_bytes (true_type); + static char alloc_name[] = "_Jv_AllocObject"; + use_java_new = 1; + alloc_decl = IDENTIFIER_GLOBAL_VALUE (get_identifier (alloc_name)); + if (alloc_decl == NULL_TREE) + fatal("call to Java constructor, while `%s' undefined", alloc_name); + class_addr = build1 (ADDR_EXPR, jclass_node, class_decl); + rval = build_function_call (alloc_decl, + tree_cons (NULL_TREE, class_addr, + build_tree_list (NULL_TREE, + class_size))); + rval = cp_convert (build_pointer_type (true_type), rval); + } + else + { + int susp = 0; + + if (flag_exceptions) + /* We will use RVAL when generating an exception handler for + this new-expression, so we must save it. */ + susp = suspend_momentary (); + + rval = build_op_new_call + (code, true_type, expr_tree_cons (NULL_TREE, size, placement), + LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL)); + rval = cp_convert (build_pointer_type (true_type), rval); + + if (flag_exceptions) + resume_momentary (susp); + } + + /* unless an allocation function is declared with an empty excep- + tion-specification (_except.spec_), throw(), it indicates failure to + allocate storage by throwing a bad_alloc exception (clause _except_, + _lib.bad.alloc_); it returns a non-null pointer otherwise If the allo- + cation function is declared with an empty exception-specification, + throw(), it returns null to indicate failure to allocate storage and a + non-null pointer otherwise. + + So check for a null exception spec on the op new we just called. */ + + nothrow = 0; + if (rval) + { + /* The CALL_EXPR. */ + tree t = TREE_OPERAND (rval, 0); + /* The function. */ + t = TREE_OPERAND (TREE_OPERAND (t, 0), 0); + nothrow = TYPE_NOTHROW_P (TREE_TYPE (t)); + } + check_new = (flag_check_new || nothrow) && ! use_java_new; + + if ((check_new || flag_exceptions) && rval) + { + alloc_expr = get_target_expr (rval); + alloc_node = rval = TREE_OPERAND (alloc_expr, 0); + } + else + alloc_expr = NULL_TREE; + + /* if rval is NULL_TREE I don't have to allocate it, but are we totally + sure we have some extra bytes in that case for the BI_header_size + cookies? And how does that interact with the code below? (mrs) */ + /* Finish up some magic for new'ed arrays */ + if (use_cookie && rval != NULL_TREE) + { + tree extra = BI_header_size; + tree cookie, exp1; + rval = convert (string_type_node, rval); /* for ptr arithmetic */ + rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra)); + /* Store header info. */ + cookie = build_indirect_ref (build (MINUS_EXPR, + build_pointer_type (BI_header_type), + rval, extra), NULL_PTR); + exp1 = build (MODIFY_EXPR, void_type_node, + build_component_ref (cookie, nc_nelts_field_id, + NULL_TREE, 0), + nelts); + TREE_SIDE_EFFECTS (exp1) = 1; + rval = cp_convert (build_pointer_type (true_type), rval); + rval = build_compound_expr + (expr_tree_cons (NULL_TREE, exp1, + build_expr_list (NULL_TREE, rval))); + } + + if (rval == error_mark_node) + return error_mark_node; + + /* Don't call any constructors or do any initialization. */ + if (init == void_type_node) + goto done; + + if (TYPE_NEEDS_CONSTRUCTING (type) || init) + { + if (! TYPE_NEEDS_CONSTRUCTING (type) + && ! IS_AGGR_TYPE (type) && ! has_array) + { + /* We are processing something like `new int (10)', which + means allocate an int, and initialize it with 10. */ + tree deref; + tree deref_type; + + /* At present RVAL is a temporary variable, created to hold + the value from the call to `operator new'. We transform + it to (*RVAL = INIT, RVAL). */ + rval = save_expr (rval); + deref = build_indirect_ref (rval, NULL_PTR); + + /* Even for something like `new const int (10)' we must + allow the expression to be non-const while we do the + initialization. */ + deref_type = TREE_TYPE (deref); + if (CP_TYPE_CONST_P (deref_type)) + TREE_TYPE (deref) + = cp_build_qualified_type (deref_type, + CP_TYPE_QUALS (deref_type) + & ~TYPE_QUAL_CONST); + TREE_READONLY (deref) = 0; + + if (TREE_CHAIN (init) != NULL_TREE) + pedwarn ("initializer list being treated as compound expression"); + else if (TREE_CODE (init) == CONSTRUCTOR) + { + pedwarn ("initializer list appears where operand should be used"); + init = TREE_OPERAND (init, 1); + } + init = build_compound_expr (init); + + init = convert_for_initialization (deref, type, init, LOOKUP_NORMAL, + "new", NULL_TREE, 0); + rval = build (COMPOUND_EXPR, TREE_TYPE (rval), + build_modify_expr (deref, NOP_EXPR, init), + rval); + TREE_NO_UNUSED_WARNING (rval) = 1; + TREE_SIDE_EFFECTS (rval) = 1; + } + else if (! has_array) + { + tree newrval; + /* Constructors are never virtual. If it has an initialization, we + need to complain if we aren't allowed to use the ctor that took + that argument. */ + int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN; + + if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type)) + { + if (TYPE_USES_PVBASES (true_type) + && !flag_vtable_thunks_compat) + { + init = expr_tree_cons (NULL_TREE, vlist_zero_node, init); + flags |= LOOKUP_HAS_VLIST; + } + init = expr_tree_cons (NULL_TREE, integer_one_node, init); + flags |= LOOKUP_HAS_IN_CHARGE; + } + + if (use_java_new) + rval = save_expr (rval); + newrval = rval; + + if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE) + newrval = build_indirect_ref (newrval, NULL_PTR); + + newrval = build_method_call (newrval, ctor_identifier, + init, TYPE_BINFO (true_type), flags); + + if (newrval == NULL_TREE || newrval == error_mark_node) + return error_mark_node; + + /* Java constructors compiled by jc1 do not return this. */ + if (use_java_new) + newrval = build (COMPOUND_EXPR, TREE_TYPE (newrval), + newrval, rval); + rval = newrval; + TREE_HAS_CONSTRUCTOR (rval) = 1; + } + else + rval = build (VEC_INIT_EXPR, TREE_TYPE (rval), + save_expr (rval), init, nelts); + + /* If any part of the object initialization terminates by throwing an + exception and a suitable deallocation function can be found, the + deallocation function is called to free the memory in which the + object was being constructed, after which the exception continues + to propagate in the context of the new-expression. If no + unambiguous matching deallocation function can be found, + propagating the exception does not cause the object's memory to be + freed. */ + if (flag_exceptions && alloc_expr && ! use_java_new) + { + enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR; + tree cleanup, fn = NULL_TREE; + int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL); + + /* All cleanups must last longer than normal. */ + int yes = suspend_momentary (); + + if (placement) + { + flags |= LOOKUP_SPECULATIVELY; + + /* We expect alloc_expr to look like a TARGET_EXPR around + a NOP_EXPR around the CALL_EXPR we want. */ + fn = TREE_OPERAND (alloc_expr, 1); + fn = TREE_OPERAND (fn, 0); + } + + /* Copy size to the saveable obstack. */ + size = mapcar (size, permanent_p); + + cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn); + + resume_momentary (yes); + + /* Ack! First we allocate the memory. Then we set our sentry + variable to true, and expand a cleanup that deletes the memory + if sentry is true. Then we run the constructor and store the + returned pointer in buf. Then we clear sentry and return buf. */ + + if (cleanup) + { + tree end, sentry, begin, buf, t = TREE_TYPE (rval); + + begin = get_target_expr (boolean_true_node); + sentry = TREE_OPERAND (begin, 0); + + yes = suspend_momentary (); + TREE_OPERAND (begin, 2) + = build (COND_EXPR, void_type_node, sentry, + cleanup, void_zero_node); + resume_momentary (yes); + + rval = get_target_expr (rval); + + end = build (MODIFY_EXPR, TREE_TYPE (sentry), + sentry, boolean_false_node); + TREE_SIDE_EFFECTS (end) = 1; + + buf = TREE_OPERAND (rval, 0); + + rval = build (COMPOUND_EXPR, t, begin, + build (COMPOUND_EXPR, t, rval, + build (COMPOUND_EXPR, t, end, buf))); + } + } + } + else if (CP_TYPE_CONST_P (true_type)) + cp_error ("uninitialized const in `new' of `%#T'", true_type); + + done: + + if (alloc_expr && rval == alloc_node) + { + rval = TREE_OPERAND (alloc_expr, 1); + alloc_expr = NULL_TREE; + } + + if (check_new && alloc_expr) + { + /* Did we modify the storage? */ + tree ifexp = build_binary_op (NE_EXPR, alloc_node, + integer_zero_node); + rval = build_conditional_expr (ifexp, rval, alloc_node); + } + + if (alloc_expr) + rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval); + + if (rval && TREE_TYPE (rval) != build_pointer_type (type)) + { + /* The type of new int [3][3] is not int *, but int [3] * */ + rval = build_c_cast (build_pointer_type (type), rval); + } + + return rval; +} + +static tree +build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, + use_global_delete) + tree base, maxindex, type; + tree auto_delete_vec, auto_delete; + int use_global_delete; +{ + tree virtual_size; + tree ptype = build_pointer_type (type = complete_type (type)); + tree size_exp = size_in_bytes (type); + + /* Temporary variables used by the loop. */ + tree tbase, tbase_init; + + /* This is the body of the loop that implements the deletion of a + single element, and moves temp variables to next elements. */ + tree body; + + /* This is the LOOP_EXPR that governs the deletion of the elements. */ + tree loop; + + /* This is the thing that governs what to do after the loop has run. */ + tree deallocate_expr = 0; + + /* This is the BIND_EXPR which holds the outermost iterator of the + loop. It is convenient to set this variable up and test it before + executing any other code in the loop. + This is also the containing expression returned by this function. */ + tree controller = NULL_TREE; + + if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type)) + { + loop = integer_zero_node; + goto no_destructor; + } + + /* The below is short by BI_header_size */ + virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex)); + + tbase = build_decl (VAR_DECL, NULL_TREE, ptype); + tbase_init = build_modify_expr (tbase, NOP_EXPR, + fold (build (PLUS_EXPR, ptype, + base, + virtual_size))); + DECL_REGISTER (tbase) = 1; + controller = build (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE); + TREE_SIDE_EFFECTS (controller) = 1; + + if (auto_delete != integer_zero_node + && auto_delete != integer_two_node) + { + tree base_tbd = cp_convert (ptype, + build_binary_op (MINUS_EXPR, + cp_convert (ptr_type_node, base), + BI_header_size)); + /* This is the real size */ + virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); + body = build_expr_list (NULL_TREE, + build_x_delete (base_tbd, + 2 | use_global_delete, + virtual_size)); + body = build (COND_EXPR, void_type_node, + build (BIT_AND_EXPR, integer_type_node, + auto_delete, integer_one_node), + body, integer_zero_node); + } + else + body = NULL_TREE; + + body = expr_tree_cons (NULL_TREE, + build_delete (ptype, tbase, auto_delete, + LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1), + body); + + body = expr_tree_cons (NULL_TREE, + build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)), + body); + + body = expr_tree_cons (NULL_TREE, + build (EXIT_EXPR, void_type_node, + build (EQ_EXPR, boolean_type_node, base, tbase)), + body); + + loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body)); + + loop = expr_tree_cons (NULL_TREE, tbase_init, + expr_tree_cons (NULL_TREE, loop, NULL_TREE)); + loop = build_compound_expr (loop); + + no_destructor: + /* If the delete flag is one, or anything else with the low bit set, + delete the storage. */ + if (auto_delete_vec == integer_zero_node) + deallocate_expr = integer_zero_node; + else + { + tree base_tbd; + + /* The below is short by BI_header_size */ + virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex)); + + if (! TYPE_VEC_NEW_USES_COOKIE (type)) + /* no header */ + base_tbd = base; + else + { + base_tbd = cp_convert (ptype, + build_binary_op (MINUS_EXPR, + cp_convert (string_type_node, base), + BI_header_size)); + /* True size with header. */ + virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); + } + deallocate_expr = build_x_delete (base_tbd, + 2 | use_global_delete, + virtual_size); + if (auto_delete_vec != integer_one_node) + deallocate_expr = build (COND_EXPR, void_type_node, + build (BIT_AND_EXPR, integer_type_node, + auto_delete_vec, integer_one_node), + deallocate_expr, integer_zero_node); + } + + if (loop && deallocate_expr != integer_zero_node) + { + body = expr_tree_cons (NULL_TREE, loop, + expr_tree_cons (NULL_TREE, deallocate_expr, NULL_TREE)); + body = build_compound_expr (body); + } + else + body = loop; + + /* Outermost wrapper: If pointer is null, punt. */ + body = build (COND_EXPR, void_type_node, + build (NE_EXPR, boolean_type_node, base, integer_zero_node), + body, integer_zero_node); + body = build1 (NOP_EXPR, void_type_node, body); + + if (controller) + { + TREE_OPERAND (controller, 1) = body; + return controller; + } + else + return cp_convert (void_type_node, body); +} + +/* Protect the vector initialization with a try-block so that we can + destroy the first few elements if constructing a later element + causes an exception to be thrown. TYPE is the type of the array + elements. */ + +static void +expand_vec_init_try_block (type) + tree type; +{ + if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions) + return; + + /* The code we generate looks like: + + try { + // Initialize the vector. + } catch (...) { + // Destory the elements that need destroying. + throw; + } + + Here we're just beginning the `try'. */ + + expand_eh_region_start (); +} + +/* Add code to destroy the array elements constructed so far if the + construction of some element in the array causes an exception to be + thrown. RVAL is the address of the last element in the array. + TYPE is the type of the array elements. MAXINDEX is the maximum + allowable index into the array. ITERATOR is an integer variable + indicating how many elements remain to be constructed. */ + +static void +expand_vec_init_catch_clause (rval, type, maxindex, iterator) + tree rval; + tree type; + tree maxindex; + tree iterator; +{ + tree e; + tree cleanup; + + if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions) + return; + + /* We have to ensure that this can live to the cleanup expansion + time, since we know it is only ever needed once, generate code + now. */ + push_obstacks_nochange (); + resume_temporary_allocation (); + + cleanup = make_node (RTL_EXPR); + TREE_TYPE (cleanup) = void_type_node; + RTL_EXPR_RTL (cleanup) = const0_rtx; + TREE_SIDE_EFFECTS (cleanup) = 1; + do_pending_stack_adjust (); + start_sequence_for_rtl_expr (cleanup); + + e = build_vec_delete_1 (rval, + build_binary_op (MINUS_EXPR, maxindex, + iterator), + type, + /*auto_delete_vec=*/integer_zero_node, + /*auto_delete=*/integer_zero_node, + /*use_global_delete=*/0); + expand_expr (e, const0_rtx, VOIDmode, EXPAND_NORMAL); + + do_pending_stack_adjust (); + RTL_EXPR_SEQUENCE (cleanup) = get_insns (); + end_sequence (); + cleanup = protect_with_terminate (cleanup); + expand_eh_region_end (cleanup); + pop_obstacks (); +} + +/* `expand_vec_init' performs initialization of a vector of aggregate + types. + + DECL is passed only for error reporting, and provides line number + and source file name information. + BASE is the space where the vector will be. + MAXINDEX is the maximum index of the array (one less than the + number of elements). + INIT is the (possibly NULL) initializer. + + FROM_ARRAY is 0 if we should init everything with INIT + (i.e., every element initialized from INIT). + FROM_ARRAY is 1 if we should index into INIT in parallel + with initialization of DECL. + FROM_ARRAY is 2 if we should index into INIT in parallel, + but use assignment instead of initialization. */ + +tree +expand_vec_init (decl, base, maxindex, init, from_array) + tree decl, base, maxindex, init; + int from_array; +{ + tree rval; + tree base2 = NULL_TREE; + tree type = TREE_TYPE (TREE_TYPE (base)); + tree size; + tree itype = NULL_TREE; + tree iterator; + int num_initialized_elts = 0; + + maxindex = cp_convert (ptrdiff_type_node, maxindex); + if (maxindex == error_mark_node) + return error_mark_node; + + if (current_function_decl == NULL_TREE) + { + rval = make_tree_vec (3); + TREE_VEC_ELT (rval, 0) = base; + TREE_VEC_ELT (rval, 1) = maxindex; + TREE_VEC_ELT (rval, 2) = init; + return rval; + } + + size = size_in_bytes (type); + + base = default_conversion (base); + base = cp_convert (build_pointer_type (type), base); + rval = get_temp_regvar (build_pointer_type (type), base); + base = get_temp_regvar (build_pointer_type (type), base); + iterator = get_temp_regvar (ptrdiff_type_node, maxindex); + + /* Protect the entire array initialization so that we can destroy + the partially constructed array if an exception is thrown. */ + expand_vec_init_try_block (type); + + if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR + && (!decl || same_type_p (TREE_TYPE (init), TREE_TYPE (decl)))) + { + /* Do non-default initialization resulting from brace-enclosed + initializers. */ + + tree elts; + tree baseref = build1 (INDIRECT_REF, type, base); + + from_array = 0; + + for (elts = CONSTRUCTOR_ELTS (init); elts; elts = TREE_CHAIN (elts)) + { + tree elt = TREE_VALUE (elts); + + num_initialized_elts++; + + if (IS_AGGR_TYPE (type) || TREE_CODE (type) == ARRAY_TYPE) + expand_aggr_init (baseref, elt, 0); + else + expand_assignment (baseref, elt, 0, 0); + + expand_assignment (base, + build (PLUS_EXPR, build_pointer_type (type), + base, size), + 0, 0); + expand_assignment (iterator, + build (MINUS_EXPR, ptrdiff_type_node, + iterator, integer_one_node), + 0, 0); + } + + /* Clear out INIT so that we don't get confused below. */ + init = NULL_TREE; + + if (obey_regdecls) + use_variable (DECL_RTL (base)); + } + else if (from_array) + { + /* If initializing one array from another, initialize element by + element. We rely upon the below calls the do argument + checking. */ + if (decl == NULL_TREE) + { + sorry ("initialization of array from dissimilar array type"); + return error_mark_node; + } + if (init) + { + base2 = default_conversion (init); + itype = TREE_TYPE (base2); + base2 = get_temp_regvar (itype, base2); + itype = TREE_TYPE (itype); + } + else if (TYPE_LANG_SPECIFIC (type) + && TYPE_NEEDS_CONSTRUCTING (type) + && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) + { + error ("initializer ends prematurely"); + return error_mark_node; + } + } + + /* Now, default-initialize any remaining elements. We don't need to + do that if a) the type does not need constructing, or b) we've + already initialized all the elements. + + We do need to keep going if we're copying an array. */ + + if (from_array + || (TYPE_NEEDS_CONSTRUCTING (type) + && !(TREE_CODE (maxindex) == INTEGER_CST + && num_initialized_elts == TREE_INT_CST_LOW (maxindex) + 1))) + { + /* If the ITERATOR is equal to -1, then we don't have to loop; + we've already initialized all the elements. */ + expand_start_cond (build (NE_EXPR, boolean_type_node, + iterator, minus_one), + 0); + + /* Otherwise, loop through the elements. */ + expand_start_loop_continue_elsewhere (1); + + /* The initialization of each array element is a full-expression. */ + expand_start_target_temps (); + + if (from_array) + { + tree to = build1 (INDIRECT_REF, type, base); + tree from; + + if (base2) + from = build1 (INDIRECT_REF, itype, base2); + else + from = NULL_TREE; + + if (from_array == 2) + expand_expr_stmt (build_modify_expr (to, NOP_EXPR, from)); + else if (TYPE_NEEDS_CONSTRUCTING (type)) + expand_aggr_init (to, from, 0); + else if (from) + expand_assignment (to, from, 0, 0); + else + my_friendly_abort (57); + } + else if (TREE_CODE (type) == ARRAY_TYPE) + { + if (init != 0) + sorry ("cannot initialize multi-dimensional array with initializer"); + expand_vec_init (decl, + build1 (NOP_EXPR, + build_pointer_type (TREE_TYPE + (type)), + base), + array_type_nelts (type), 0, 0); + } + else + expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0); + + expand_assignment (base, + build (PLUS_EXPR, build_pointer_type (type), + base, size), 0, 0); + if (base2) + expand_assignment (base2, + build (PLUS_EXPR, build_pointer_type (type), + base2, size), 0, 0); + + /* Cleanup any temporaries needed for the initial value. */ + expand_end_target_temps (); + + expand_loop_continue_here (); + expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node, + build (PREDECREMENT_EXPR, + ptrdiff_type_node, + iterator, + integer_one_node), + minus_one)); + + if (obey_regdecls) + { + use_variable (DECL_RTL (base)); + if (base2) + use_variable (DECL_RTL (base2)); + } + + expand_end_loop (); + expand_end_cond (); + } + + /* Make sure to cleanup any partially constructed elements. */ + expand_vec_init_catch_clause (rval, type, maxindex, iterator); + + if (obey_regdecls) + { + use_variable (DECL_RTL (iterator)); + use_variable (DECL_RTL (rval)); + } + + return rval; +} + +/* Free up storage of type TYPE, at address ADDR. + + TYPE is a POINTER_TYPE and can be ptr_type_node for no special type + of pointer. + + VIRTUAL_SIZE is the amount of storage that was allocated, and is + used as the second argument to operator delete. It can include + things like padding and magic size cookies. It has virtual in it, + because if you have a base pointer and you delete through a virtual + destructor, it should be the size of the dynamic object, not the + static object, see Free Store 12.5 ANSI C++ WP. + + This does not call any destructors. */ + +tree +build_x_delete (addr, which_delete, virtual_size) + tree addr; + int which_delete; + tree virtual_size; +{ + int use_global_delete = which_delete & 1; + int use_vec_delete = !!(which_delete & 2); + enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR; + int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL); + + return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE); +} + +/* Generate a call to a destructor. TYPE is the type to cast ADDR to. + ADDR is an expression which yields the store to be destroyed. + AUTO_DELETE is nonzero if a call to DELETE should be made or not. + If in the program, (AUTO_DELETE & 2) is non-zero, we tear down the + virtual baseclasses. + If in the program, (AUTO_DELETE & 1) is non-zero, then we deallocate. + + FLAGS is the logical disjunction of zero or more LOOKUP_ + flags. See cp-tree.h for more info. + + This function does not delete an object's virtual base classes. */ + +tree +build_delete (type, addr, auto_delete, flags, use_global_delete) + tree type, addr; + tree auto_delete; + int flags; + int use_global_delete; +{ + tree member; + tree expr; + tree ref; + + if (addr == error_mark_node) + return error_mark_node; + + /* Can happen when CURRENT_EXCEPTION_OBJECT gets its type + set to `error_mark_node' before it gets properly cleaned up. */ + if (type == error_mark_node) + return error_mark_node; + + type = TYPE_MAIN_VARIANT (type); + + if (TREE_CODE (type) == POINTER_TYPE) + { + type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); + if (type != void_type_node && !complete_type_or_else (type, addr)) + return error_mark_node; + if (TREE_CODE (type) == ARRAY_TYPE) + goto handle_array; + if (! IS_AGGR_TYPE (type)) + { + /* Call the builtin operator delete. */ + return build_builtin_delete_call (addr); + } + if (TREE_SIDE_EFFECTS (addr)) + addr = save_expr (addr); + + /* throw away const and volatile on target type of addr */ + addr = convert_force (build_pointer_type (type), addr, 0); + ref = build_indirect_ref (addr, NULL_PTR); + } + else if (TREE_CODE (type) == ARRAY_TYPE) + { + handle_array: + if (TREE_SIDE_EFFECTS (addr)) + addr = save_expr (addr); + if (TYPE_DOMAIN (type) == NULL_TREE) + { + error ("unknown array size in delete"); + return error_mark_node; + } + return build_vec_delete (addr, array_type_nelts (type), + auto_delete, integer_zero_node, + use_global_delete); + } + else + { + /* Don't check PROTECT here; leave that decision to the + destructor. If the destructor is accessible, call it, + else report error. */ + addr = build_unary_op (ADDR_EXPR, addr, 0); + if (TREE_SIDE_EFFECTS (addr)) + addr = save_expr (addr); + + if (TREE_CONSTANT (addr)) + addr = convert_pointer_to (type, addr); + else + addr = convert_force (build_pointer_type (type), addr, 0); + + ref = build_indirect_ref (addr, NULL_PTR); + } + + my_friendly_assert (IS_AGGR_TYPE (type), 220); + + if (! TYPE_NEEDS_DESTRUCTOR (type)) + { + if (auto_delete == integer_zero_node) + return void_zero_node; + + return build_op_delete_call + (DELETE_EXPR, addr, c_sizeof_nowarn (type), + LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL), + NULL_TREE); + } + + /* Below, we will reverse the order in which these calls are made. + If we have a destructor, then that destructor will take care + of the base classes; otherwise, we must do that here. */ + if (TYPE_HAS_DESTRUCTOR (type)) + { + tree passed_auto_delete; + tree do_delete = NULL_TREE; + tree ifexp; + + if (use_global_delete) + { + tree cond = fold (build (BIT_AND_EXPR, integer_type_node, + auto_delete, integer_one_node)); + tree call = build_builtin_delete_call (addr); + + cond = fold (build (COND_EXPR, void_type_node, cond, + call, void_zero_node)); + if (cond != void_zero_node) + do_delete = cond; + + passed_auto_delete = fold (build (BIT_AND_EXPR, integer_type_node, + auto_delete, integer_two_node)); + } + else + passed_auto_delete = auto_delete; + + /* Maybe pass vlist pointer to destructor. */ + if (TYPE_USES_PVBASES (type)) + { + /* Pass vlist_zero even if in backwards compatibility mode, + as the extra argument should not hurt if it is not used. */ + expr = build_expr_list (NULL_TREE, vlist_zero_node); + flags |= LOOKUP_HAS_VLIST; + } + else + expr = NULL_TREE; + + expr = expr_tree_cons (NULL_TREE, passed_auto_delete, expr); + + expr = build_method_call (ref, dtor_identifier, expr, + NULL_TREE, flags); + + if (do_delete) + expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete); + + if (flags & LOOKUP_DESTRUCTOR) + /* Explicit destructor call; don't check for null pointer. */ + ifexp = integer_one_node; + else + /* Handle deleting a null pointer. */ + ifexp = fold (build_binary_op (NE_EXPR, addr, integer_zero_node)); + + if (ifexp != integer_one_node) + expr = build (COND_EXPR, void_type_node, + ifexp, expr, void_zero_node); + + return expr; + } + else + { + /* We only get here from finish_function for a destructor. */ + tree binfos = BINFO_BASETYPES (TYPE_BINFO (type)); + int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; + tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE; + tree exprstmt = NULL_TREE; + tree parent_auto_delete = auto_delete; + tree cond; + + /* Set this again before we call anything, as we might get called + recursively. */ + TYPE_HAS_DESTRUCTOR (type) = 1; + + /* If we have member delete or vbases, we call delete in + finish_function. */ + if (auto_delete == integer_zero_node) + cond = NULL_TREE; + else if (base_binfo == NULL_TREE + || ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))) + { + cond = build (COND_EXPR, void_type_node, + build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node), + build_builtin_delete_call (addr), + void_zero_node); + } + else + cond = NULL_TREE; + + if (cond) + exprstmt = build_expr_list (NULL_TREE, cond); + + if (base_binfo + && ! TREE_VIA_VIRTUAL (base_binfo) + && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))) + { + tree this_auto_delete; + + /* Should the base invoke delete? */ + if (BINFO_OFFSET_ZEROP (base_binfo)) + this_auto_delete = parent_auto_delete; + else + this_auto_delete = integer_zero_node; + + expr = build_base_dtor_call (ref, base_binfo, this_auto_delete); + exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); + } + + /* Take care of the remaining baseclasses. */ + for (i = 1; i < n_baseclasses; i++) + { + base_binfo = TREE_VEC_ELT (binfos, i); + if (! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)) + || TREE_VIA_VIRTUAL (base_binfo)) + continue; + + expr = build_base_dtor_call (ref, base_binfo, integer_zero_node); + + exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); + } + + for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member)) + { + if (TREE_CODE (member) != FIELD_DECL) + continue; + if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (member))) + { + tree this_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0); + tree this_type = TREE_TYPE (member); + expr = build_delete (this_type, this_member, integer_two_node, flags, 0); + exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); + } + } + + if (exprstmt) + return build_compound_expr (exprstmt); + /* Virtual base classes make this function do nothing. */ + return void_zero_node; + } +} + +/* For type TYPE, delete the virtual baseclass objects of DECL. */ + +tree +build_vbase_delete (type, decl) + tree type, decl; +{ + tree vbases = CLASSTYPE_VBASECLASSES (type); + tree result = NULL_TREE; + tree addr = build_unary_op (ADDR_EXPR, decl, 0); + + my_friendly_assert (addr != error_mark_node, 222); + + while (vbases) + { + tree this_addr = convert_force (build_pointer_type (BINFO_TYPE (vbases)), + addr, 0); + result = expr_tree_cons (NULL_TREE, + build_delete (TREE_TYPE (this_addr), this_addr, + integer_zero_node, + LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0), + result); + vbases = TREE_CHAIN (vbases); + } + return build_compound_expr (nreverse (result)); +} + +/* Build a C++ vector delete expression. + MAXINDEX is the number of elements to be deleted. + ELT_SIZE is the nominal size of each element in the vector. + BASE is the expression that should yield the store to be deleted. + This function expands (or synthesizes) these calls itself. + AUTO_DELETE_VEC says whether the container (vector) should be deallocated. + AUTO_DELETE say whether each item in the container should be deallocated. + + This also calls delete for virtual baseclasses of elements of the vector. + + Update: MAXINDEX is no longer needed. The size can be extracted from the + start of the vector for pointers, and from the type for arrays. We still + use MAXINDEX for arrays because it happens to already have one of the + values we'd have to extract. (We could use MAXINDEX with pointers to + confirm the size, and trap if the numbers differ; not clear that it'd + be worth bothering.) */ + +tree +build_vec_delete (base, maxindex, auto_delete_vec, auto_delete, + use_global_delete) + tree base, maxindex; + tree auto_delete_vec, auto_delete; + int use_global_delete; +{ + tree type; + + if (TREE_CODE (base) == OFFSET_REF) + base = resolve_offset_ref (base); + + type = TREE_TYPE (base); + + base = stabilize_reference (base); + + /* Since we can use base many times, save_expr it. */ + if (TREE_SIDE_EFFECTS (base)) + base = save_expr (base); + + if (TREE_CODE (type) == POINTER_TYPE) + { + /* Step back one from start of vector, and read dimension. */ + tree cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type), + base, BI_header_size); + tree cookie = build_indirect_ref (cookie_addr, NULL_PTR); + maxindex = build_component_ref (cookie, nc_nelts_field_id, NULL_TREE, 0); + do + type = TREE_TYPE (type); + while (TREE_CODE (type) == ARRAY_TYPE); + } + else if (TREE_CODE (type) == ARRAY_TYPE) + { + /* get the total number of things in the array, maxindex is a bad name */ + maxindex = array_type_nelts_total (type); + while (TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); + base = build_unary_op (ADDR_EXPR, base, 1); + } + else + { + if (base != error_mark_node) + error ("type to vector delete is neither pointer or array type"); + return error_mark_node; + } + + return build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, + use_global_delete); +} Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/init.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/method.c =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/method.c (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/method.c (revision 60969) @@ -0,0 +1,2656 @@ +/* Handle the hair of processing (but not expanding) inline functions. + Also manage function and variable name overloading. + Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@cygnus.com) + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +#ifndef __GNUC__ +#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" +#include "tree.h" +#include "cp-tree.h" +#include "obstack.h" +#include "rtl.h" +#include "expr.h" +#include "output.h" +#include "hard-reg-set.h" +#include "flags.h" +#include "toplev.h" +#include "decl.h" + +/* TREE_LIST of the current inline functions that need to be + processed. */ +struct pending_inline *pending_inlines; + +int static_labelno; + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +/* Obstack where we build text strings for overloading, etc. */ +static struct obstack scratch_obstack; +static char *scratch_firstobj; + +static void icat PROTO((HOST_WIDE_INT)); +static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT)); +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 build_overload_identifier PROTO((tree)); +static void build_qualified_name PROTO((tree)); +static void build_overload_value PROTO((tree, tree, int)); +static void issue_nrepeats PROTO((int, tree)); +static char *build_mangled_name PROTO((tree,int,int)); +static void process_modifiers PROTO((tree)); +static void process_overload_item PROTO((tree,int)); +static void do_build_assign_ref PROTO((tree)); +static void do_build_copy_constructor PROTO((tree)); +static tree largest_union_member PROTO((tree)); +static void build_template_template_parm_names PROTO((tree)); +static void build_template_parm_names PROTO((tree, tree)); +static void build_underscore_int PROTO((int)); +static void start_squangling PROTO((void)); +static void end_squangling PROTO((void)); +static int check_ktype PROTO((tree, int)); +static int issue_ktype PROTO((tree)); +static void build_overload_scope_ref PROTO((tree)); +static void build_mangled_template_parm_index PROTO((char *, tree)); +#if HOST_BITS_PER_WIDE_INT >= 64 +static void build_mangled_C9x_name PROTO((int)); +#endif +static int is_back_referenceable_type PROTO((tree)); +static int check_btype PROTO((tree)); +static void build_mangled_name_for_type PROTO((tree)); +static void build_mangled_name_for_type_with_Gcode PROTO((tree, int)); +static tree build_base_path PROTO((tree, int)); + + +# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0) +# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C))) +# define OB_PUTC2(C1,C2) \ + (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2))) +# define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1)) +# define OB_PUTID(ID) \ + (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \ + IDENTIFIER_LENGTH (ID))) +# define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S))) +# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0')) +# define OB_LAST() (obstack_next_free (&scratch_obstack)[-1]) + +void +init_method () +{ + gcc_obstack_init (&scratch_obstack); + scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0); +} + +/* This must be large enough to hold any printed integer or floating-point + value. */ +static char digit_buffer[128]; + +/* Move inline function definitions out of structure so that they + can be processed normally. CNAME is the name of the class + we are working from, METHOD_LIST is the list of method lists + of the structure. We delete friend methods here, after + saving away their inline function definitions (if any). */ + +void +do_inline_function_hair (type, friend_list) + tree type, friend_list; +{ + tree method = TYPE_METHODS (type); + + if (method && TREE_CODE (method) == TREE_VEC) + { + if (TREE_VEC_ELT (method, 1)) + method = TREE_VEC_ELT (method, 1); + else if (TREE_VEC_ELT (method, 0)) + method = TREE_VEC_ELT (method, 0); + else + method = TREE_VEC_ELT (method, 2); + } + + while (method) + { + /* Do inline member functions. */ + struct pending_inline *info = DECL_PENDING_INLINE_INFO (method); + if (info) + { + tree args; + + my_friendly_assert (info->fndecl == method, 238); + args = DECL_ARGUMENTS (method); + while (args) + { + DECL_CONTEXT (args) = method; + args = TREE_CHAIN (args); + } + } + method = TREE_CHAIN (method); + } + while (friend_list) + { + tree fndecl = TREE_VALUE (friend_list); + struct pending_inline *info = DECL_PENDING_INLINE_INFO (fndecl); + if (info) + { + tree args; + + my_friendly_assert (info->fndecl == fndecl, 239); + args = DECL_ARGUMENTS (fndecl); + while (args) + { + DECL_CONTEXT (args) = fndecl; + args = TREE_CHAIN (args); + } + } + + friend_list = TREE_CHAIN (friend_list); + } +} + +/* Here is where overload code starts. */ + +/* type tables for K and B type compression */ +static tree *btypelist = NULL; +static tree *ktypelist = NULL; +static int maxbsize = 0; +static int maxksize = 0; + +/* number of each type seen */ +static int maxbtype = 0; +static int maxktype = 0; + +/* Array of types seen so far in top-level call to `build_mangled_name'. + Allocated and deallocated by caller. */ +static tree *typevec = NULL; +static int typevec_size; + +/* Number of types interned by `build_mangled_name' so far. */ +static int maxtype = 0; + +/* 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. */ +static int numeric_output_need_bar; + +static __inline void +start_squangling () +{ + if (flag_do_squangling) + { + nofold = 0; + maxbtype = 0; + maxktype = 0; + maxbsize = 50; + maxksize = 50; + btypelist = (tree *)xmalloc (sizeof (tree) * maxbsize); + ktypelist = (tree *)xmalloc (sizeof (tree) * maxksize); + } +} + +static __inline void +end_squangling () +{ + if (flag_do_squangling) + { + if (ktypelist) + free (ktypelist); + if (btypelist) + free (btypelist); + maxbsize = 0; + maxksize = 0; + maxbtype = 0; + maxktype = 0; + ktypelist = NULL; + btypelist = NULL; + } +} + +/* Code to concatenate an asciified integer to a string. */ + +static __inline void +icat (i) + HOST_WIDE_INT i; +{ + unsigned HOST_WIDE_INT ui; + + /* Handle this case first, to go really quickly. For many common values, + the result of ui/10 below is 1. */ + if (i == 1) + { + OB_PUTC ('1'); + return; + } + + if (i >= 0) + ui = i; + else + { + OB_PUTC ('m'); + ui = -i; + } + + if (ui >= 10) + icat (ui / 10); + + OB_PUTC ('0' + (ui % 10)); +} + +static void +dicat (lo, hi) + HOST_WIDE_INT lo, hi; +{ + unsigned HOST_WIDE_INT ulo, uhi, qlo, qhi; + + if (hi >= 0) + { + uhi = hi; + ulo = lo; + } + else + { + uhi = (lo == 0 ? -hi : -hi-1); + ulo = -lo; + } + if (uhi == 0 + && ulo < ((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1))) + { + icat (ulo); + return; + } + /* Divide 2^HOST_WIDE_INT*uhi+ulo by 10. */ + qhi = uhi / 10; + uhi = uhi % 10; + qlo = uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) / 5); + qlo += ulo / 10; + ulo = ulo % 10; + ulo += uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) % 5) + * 2; + qlo += ulo / 10; + ulo = ulo % 10; + /* Quotient is 2^HOST_WIDE_INT*qhi+qlo, remainder is ulo. */ + dicat (qlo, qhi); + OB_PUTC ('0' + ulo); +} + +/* Returns the index of TYPE in the typevec, or -1 if it's not there. */ + +static __inline int +old_backref_index (type) + tree type; +{ + int tindex = 0; + + if (! is_back_referenceable_type (type)) + return -1; + + /* The entry for this parm is at maxtype-1, so don't look there for + something to repeat. */ + for (tindex = 0; tindex < maxtype - 1; ++tindex) + if (same_type_p (typevec[tindex], type)) + break; + + if (tindex == maxtype - 1) + return -1; + + return tindex; +} + +/* Old mangling style: If TYPE has already been used in the parameter list, + emit a backward reference and return non-zero; otherwise, return 0. + + NREPEATS is the number of repeats we've recorded of this type, or 0 if + this is the first time we've seen it and we're just looking to see if + it had been used before. */ + +static __inline int +flush_repeats (nrepeats, type) + int nrepeats; + tree type; +{ + int tindex = old_backref_index (type); + + if (tindex == -1) + { + my_friendly_assert (nrepeats == 0, 990316); + return 0; + } + + if (nrepeats > 1) + { + OB_PUTC ('N'); + icat (nrepeats); + if (nrepeats > 9) + OB_PUTC ('_'); + } + else + OB_PUTC ('T'); + icat (tindex); + if (tindex > 9) + OB_PUTC ('_'); + + return 1; +} + +/* Returns nonzero iff this is a type to which we will want to make + back-references (using the `B' code). */ + +static int +is_back_referenceable_type (type) + tree type; +{ + /* For some reason, the Java folks don't want back refs on these. */ + if (TYPE_FOR_JAVA (type)) + return 0; + + switch (TREE_CODE (type)) + { + case BOOLEAN_TYPE: + if (!flag_do_squangling) + /* Even though the mangling of this is just `b', we did + historically generate back-references for it. */ + return 1; + /* Fall through. */ + + case INTEGER_TYPE: + case REAL_TYPE: + case VOID_TYPE: + /* These types have single-character manglings, so there's no + point in generating back-references. */ + return 0; + + case TEMPLATE_TYPE_PARM: + /* It would be a bit complex to demangle signatures correctly if + we generated back-references to these, and the manglings of + type parameters are short. */ + return 0; + + default: + return 1; + } +} + +/* Issue the squangling code indicating NREPEATS repetitions of TYPE, + which was the last parameter type output. */ + +static void +issue_nrepeats (nrepeats, type) + int nrepeats; + tree type; +{ + if (nrepeats == 1 && !is_back_referenceable_type (type)) + /* For types whose manglings are short, don't bother using the + repetition code if there's only one repetition, since the + repetition code will be about as long as the ordinary mangling. */ + build_mangled_name_for_type (type); + else + { + OB_PUTC ('n'); + icat (nrepeats); + if (nrepeats > 9) + OB_PUTC ('_'); + } +} + +/* Check to see if a tree node has been entered into the Kcode typelist. + If not, add it. Returns -1 if it isn't found, otherwise returns the + index. */ + +static int +check_ktype (node, add) + tree node; + int add; +{ + int x; + tree localnode = node; + + if (ktypelist == NULL) + return -1; + + if (TREE_CODE (node) == TYPE_DECL) + localnode = TREE_TYPE (node); + + for (x=0; x < maxktype; x++) + { + if (same_type_p (localnode, ktypelist[x])) + return x; + } + /* Didn't find it, so add it here. */ + if (add) + { + if (maxksize <= maxktype) + { + maxksize = maxksize* 3 / 2; + ktypelist = (tree *)xrealloc (ktypelist, sizeof (tree) * maxksize); + } + ktypelist[maxktype++] = localnode; + } + return -1; +} + + +static __inline int +issue_ktype (decl) + tree decl; +{ + int kindex; + kindex = check_ktype (decl, FALSE); + if (kindex != -1) + { + OB_PUTC ('K'); + icat (kindex); + if (kindex > 9) + OB_PUTC ('_'); + return TRUE; + } + return FALSE; +} + +/* Build a representation for DECL, which may be an entity not at + global scope. If so, a marker indicating that the name is + qualified has already been output, but the qualifying context has + not. */ + +static void +build_overload_nested_name (decl) + tree decl; +{ + tree context; + + if (ktypelist && issue_ktype (decl)) + return; + + if (decl == global_namespace) + return; + + context = CP_DECL_CONTEXT (decl); + + /* try to issue a K type, and if we can't continue the normal path */ + if (!(ktypelist && issue_ktype (context))) + { + /* For a template type parameter, we want to output an 'Xn' + rather than 'T' or some such. */ + if (TREE_CODE (context) == TEMPLATE_TYPE_PARM + || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM) + build_mangled_name_for_type (context); + else + { + if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') + context = TYPE_NAME (context); + build_overload_nested_name (context); + } + } + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + tree name = DECL_ASSEMBLER_NAME (decl); + char *label; + + ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), static_labelno); + static_labelno++; + + if (numeric_output_need_bar) + OB_PUTC ('_'); + icat (strlen (label)); + OB_PUTCP (label); + numeric_output_need_bar = 1; + } + else if (TREE_CODE (decl) == NAMESPACE_DECL) + build_overload_identifier (DECL_NAME (decl)); + else /* TYPE_DECL */ + build_overload_identifier (decl); +} + +/* Output the decimal representation of I. If I > 9, the decimal + representation is preceeded and followed by an underscore. */ + +static void +build_underscore_int (i) + int i; +{ + if (i > 9) + OB_PUTC ('_'); + icat (i); + if (i > 9) + OB_PUTC ('_'); +} + +static void +build_overload_scope_ref (value) + tree value; +{ + OB_PUTC2 ('Q', '2'); + numeric_output_need_bar = 0; + build_mangled_name_for_type (TREE_OPERAND (value, 0)); + build_overload_identifier (TREE_OPERAND (value, 1)); +} + +/* Encoding for an INTEGER_CST value. */ + +static void +build_overload_int (value, in_template) + tree value; + int in_template; +{ + if (in_template && TREE_CODE (value) != INTEGER_CST) + { + 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; + 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 "". 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 void f(A); */ + 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; + return; + } + + my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); + if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT) + { + 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 */ + } + /* Wordsize or smaller */ + icat (TREE_INT_CST_LOW (value)); + numeric_output_need_bar = 1; +} + + +/* Output S followed by a representation of the TEMPLATE_PARM_INDEX + supplied in INDEX. */ + +static void +build_mangled_template_parm_index (s, index) + char* s; + tree index; +{ + OB_PUTCP (s); + build_underscore_int (TEMPLATE_PARM_IDX (index)); + /* We use the LEVEL, not the ORIG_LEVEL, because the mangling is a + representation of the function from the point of view of its + type. */ + build_underscore_int (TEMPLATE_PARM_LEVEL (index)); +} + + +/* Mangling for C9X integer types (and Cygnus extensions for 128-bit + and other types) is based on the letter "I" followed by the hex + representations of the bitsize for the type in question. For + encodings that result in larger than two digits, a leading and + trailing underscore is added. + + Thus: + int1_t = 001 = I01 + int8_t = 008 = I08 + int16_t = 010 = I10 + int24_t = 018 = I18 + int32_t = 020 = I20 + int64_t = 040 = I40 + int80_t = 050 = I50 + int128_t = 080 = I80 + int256_t = 100 = I_100_ + int512_t = 200 = I_200_ + + Given an integer in decimal format, mangle according to this scheme. */ + +#if HOST_BITS_PER_WIDE_INT >= 64 +static void +build_mangled_C9x_name (bits) + int bits; +{ + char mangled[10] = ""; + + if (bits > 255) + sprintf (mangled, "I_%x_", bits); + else + sprintf (mangled, "I%.2x", bits); + + OB_PUTCP (mangled); +} +#endif + +static void +build_overload_value (type, value, in_template) + tree type, value; + int in_template; +{ + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0); + + while (TREE_CODE (value) == NON_LVALUE_EXPR + || TREE_CODE (value) == NOP_EXPR) + value = TREE_OPERAND (value, 0); + + if (numeric_output_need_bar) + { + OB_PUTC ('_'); + numeric_output_need_bar = 0; + } + + if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) + { + build_mangled_template_parm_index ("Y", value); + return; + } + + if (TYPE_PTRMEM_P (type)) + { + if (TREE_CODE (value) != PTRMEM_CST) + /* We should have already rejected this pointer to member, + since it is not a constant. */ + my_friendly_abort (0); + + /* Get the actual FIELD_DECL. */ + value = PTRMEM_CST_MEMBER (value); + my_friendly_assert (TREE_CODE (value) == FIELD_DECL, 0); + + /* Output the name of the field. */ + build_overload_identifier (DECL_NAME (value)); + return; + } + + 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"); + + my_friendly_assert (TREE_CODE (value) == REAL_CST, 244); + val = TREE_REAL_CST (value); + if (REAL_VALUE_ISNAN (val)) + { + sprintf (bufp, "NaN"); + } + else + { + if (REAL_VALUE_NEGATIVE (val)) + { + val = REAL_VALUE_NEGATE (val); + *bufp++ = 'm'; + } + if (REAL_VALUE_ISINF (val)) + { + sprintf (bufp, "Infinity"); + } + else + { + REAL_VALUE_TO_DECIMAL (val, "%.20e", bufp); + bufp = (char *) index (bufp, 'e'); + if (!bufp) + strcat (digit_buffer, "e0"); + else + { + char *p; + bufp++; + if (*bufp == '-') + { + *bufp++ = 'm'; + } + p = bufp; + if (*p == '+') + p++; + while (*p == '0') + p++; + if (*p == 0) + { + *bufp++ = '0'; + *bufp = 0; + } + else if (p != bufp) + { + while (*p) + *bufp++ = *p++; + *bufp = 0; + } + } +#ifdef NO_DOT_IN_LABEL + bufp = (char *) index (bufp, '.'); + if (bufp) + *bufp = '_'; +#endif + } + } + OB_PUTCP (digit_buffer); + numeric_output_need_bar = 1; + return; + } + case POINTER_TYPE: + if (TREE_CODE (value) == INTEGER_CST) + { + build_overload_int (value, in_template); + return; + } + else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) + { + build_mangled_template_parm_index ("", value); + numeric_output_need_bar = 1; + return; + } + + value = TREE_OPERAND (value, 0); + + /* Fall through. */ + + case REFERENCE_TYPE: + if (TREE_CODE (value) == VAR_DECL) + { + my_friendly_assert (DECL_NAME (value) != 0, 245); + build_overload_identifier (DECL_ASSEMBLER_NAME (value)); + return; + } + else if (TREE_CODE (value) == FUNCTION_DECL) + { + my_friendly_assert (DECL_NAME (value) != 0, 246); + build_overload_identifier (DECL_ASSEMBLER_NAME (value)); + return; + } + else if (TREE_CODE (value) == SCOPE_REF) + build_overload_scope_ref (value); + else + my_friendly_abort (71); + break; /* not really needed */ + + case RECORD_TYPE: + { + tree delta; + tree idx; + tree pfn; + tree delta2; + + my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 0); + + /* We'll get a ADDR_EXPR of a SCOPE_REF here if we're + mangling, an instantiation of something like: + + template class C {}; + template C x(); + + We mangle the return type of the function, and that + contains template parameters. */ + if (TREE_CODE (value) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (value, 0)) == SCOPE_REF) + { + build_overload_scope_ref (TREE_OPERAND (value, 0)); + break; + } + + my_friendly_assert (TREE_CODE (value) == PTRMEM_CST, 0); + + expand_ptrmemfunc_cst (value, &delta, &idx, &pfn, &delta2); + build_overload_int (delta, in_template); + OB_PUTC ('_'); + build_overload_int (idx, in_template); + OB_PUTC ('_'); + if (pfn) + { + numeric_output_need_bar = 0; + build_overload_identifier (DECL_ASSEMBLER_NAME + (PTRMEM_CST_MEMBER (value))); + } + else + { + OB_PUTC ('i'); + build_overload_int (delta2, in_template); + } + } + break; + + default: + sorry ("conversion of %s as template parameter", + tree_code_name [(int) TREE_CODE (type)]); + my_friendly_abort (72); + } +} + + +/* Add encodings for the declaration of template template parameters. + PARMLIST must be a TREE_VEC. */ + +static void +build_template_template_parm_names (parmlist) + tree parmlist; +{ + int i, nparms; + + my_friendly_assert (TREE_CODE (parmlist) == TREE_VEC, 246.5); + nparms = TREE_VEC_LENGTH (parmlist); + icat (nparms); + for (i = 0; i < nparms; i++) + { + tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); + if (TREE_CODE (parm) == TYPE_DECL) + { + /* This parameter is a type. */ + OB_PUTC ('Z'); + } + else if (TREE_CODE (parm) == TEMPLATE_DECL) + { + /* This parameter is a template. */ + OB_PUTC ('z'); + build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm)); + } + else + /* It's a PARM_DECL. */ + build_mangled_name_for_type (TREE_TYPE (parm)); + } +} + + +/* Add encodings for the vector of template parameters in PARMLIST, + given the vector of arguments to be substituted in ARGLIST. */ + +static void +build_template_parm_names (parmlist, arglist) + tree parmlist; + tree arglist; +{ + int i, nparms; + tree inner_args = innermost_args (arglist); + + nparms = TREE_VEC_LENGTH (parmlist); + icat (nparms); + for (i = 0; i < nparms; i++) + { + tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); + tree arg = TREE_VEC_ELT (inner_args, i); + if (TREE_CODE (parm) == TYPE_DECL) + { + /* This parameter is a type. */ + OB_PUTC ('Z'); + build_mangled_name_for_type (arg); + } + else if (TREE_CODE (parm) == TEMPLATE_DECL) + { + /* This parameter is a template. */ + if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) + /* Output parameter declaration, argument index and level. */ + build_mangled_name_for_type (arg); + else + { + /* A TEMPLATE_DECL node, output the parameter declaration + and template name */ + + OB_PUTC ('z'); + build_template_template_parm_names + (DECL_INNERMOST_TEMPLATE_PARMS (parm)); + icat (IDENTIFIER_LENGTH (DECL_NAME (arg))); + OB_PUTID (DECL_NAME (arg)); + } + } + else + { + parm = tsubst (parm, arglist, /*complain=*/1, NULL_TREE); + /* It's a PARM_DECL. */ + build_mangled_name_for_type (TREE_TYPE (parm)); + build_overload_value (TREE_TYPE (parm), arg, + uses_template_parms (arglist)); + } + } + } + +/* Output the representation for NAME, which is either a TYPE_DECL or + an IDENTIFIER. */ + +static void +build_overload_identifier (name) + tree name; +{ + if (TREE_CODE (name) == TYPE_DECL + && CLASS_TYPE_P (TREE_TYPE (name)) + && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)) + && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name))) + || (TREE_CODE (DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE + (TREE_TYPE (name)))) + == FUNCTION_DECL))) + { + /* NAME is the TYPE_DECL for a template specialization. */ + tree template, parmlist, arglist, tname; + template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name)); + arglist = CLASSTYPE_TI_ARGS (TREE_TYPE (name)); + tname = DECL_NAME (template); + parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); + OB_PUTC ('t'); + icat (IDENTIFIER_LENGTH (tname)); + OB_PUTID (tname); + build_template_parm_names (parmlist, arglist); + } + else + { + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + if (numeric_output_need_bar) + { + OB_PUTC ('_'); + numeric_output_need_bar = 0; + } + icat (IDENTIFIER_LENGTH (name)); + OB_PUTID (name); + } +} + +/* Given DECL, either a class TYPE, TYPE_DECL or FUNCTION_DECL, produce + the mangling for it. Used by build_mangled_name and build_static_name. */ + +static void +build_qualified_name (decl) + tree decl; +{ + tree context; + int i = 1; + + if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't') + decl = TYPE_NAME (decl); + + /* If DECL_ASSEMBLER_NAME has been set properly, use it. */ + if (TREE_CODE (decl) == TYPE_DECL + && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling) + { + tree id = DECL_ASSEMBLER_NAME (decl); + OB_PUTID (id); + if (ISDIGIT (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1])) + numeric_output_need_bar = 1; + return; + } + + context = decl; + /* If we can't find a Ktype, do it the hard way. */ + if (check_ktype (context, FALSE) == -1) + { + /* Count type and namespace scopes. */ + while (1) + { + context = CP_DECL_CONTEXT (context); + if (context == global_namespace) + break; + i += 1; + if (check_ktype (context, FALSE) != -1) + /* Found one! */ + break; + if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') + context = TYPE_NAME (context); + } + } + + if (i > 1) + { + OB_PUTC ('Q'); + build_underscore_int (i); + numeric_output_need_bar = 0; + } + build_overload_nested_name (decl); +} + +/* Output the mangled representation for TYPE. If EXTRA_GCODE is + non-zero, mangled names for structure/union types are intentionally + mangled differently from the method described in the ARM. */ + +static void +build_mangled_name_for_type_with_Gcode (type, extra_Gcode) + tree type; + int extra_Gcode; +{ + if (TYPE_PTRMEMFUNC_P (type)) + type = TYPE_PTRMEMFUNC_FN_TYPE (type); + process_modifiers (type); + process_overload_item (type, extra_Gcode); +} + +/* Like build_mangled_name_for_type_with_Gcode, but never outputs the + `G'. */ + +static void +build_mangled_name_for_type (type) + tree type; +{ + build_mangled_name_for_type_with_Gcode (type, 0); +} + +/* Given a list of parameters in PARMTYPES, create an unambiguous + overload string. Should distinguish any type that C (or C++) can + distinguish. I.e., pointers to functions are treated correctly. + + Caller must deal with whether a final `e' goes on the end or not. + + Any default conversions must take place before this function + is called. + + BEGIN and END control initialization and finalization of the + obstack where we build the string. */ + +char * +build_overload_name (parmtypes, begin, end) + tree parmtypes; + int begin, end; +{ + char *ret; + start_squangling (); + ret = build_mangled_name (parmtypes, begin, end); + end_squangling (); + return ret ; +} + +/* Output the mangled representation for PARMTYPES. If PARMTYPES is a + TREE_LIST, then it is a list of parameter types. Otherwise, + PARMTYPES must be a single type. */ + +static char * +build_mangled_name (parmtypes, begin, end) + tree parmtypes; + int begin, end; +{ + if (begin) + OB_INIT (); + + if (TREE_CODE (parmtypes) != TREE_LIST) + /* There is only one type. */ + build_mangled_name_for_type (parmtypes); + else + { + /* There are several types in a parameter list. */ + int nrepeats = 0; + int old_style_repeats = !flag_do_squangling && !nofold && typevec; + tree last_type = NULL_TREE; + + for (; parmtypes && parmtypes != void_list_node; + parmtypes = TREE_CHAIN (parmtypes)) + { + /* We used to call canonical_type_variant here, but that isn't + good enough; it doesn't handle pointers to typedef types. So + we can't just set TREE_USED to say we've seen a type already; + we have to check each of the earlier types with same_type_p. */ + tree parmtype = TREE_VALUE (parmtypes); + + if (old_style_repeats) + { + /* Every argument gets counted. */ + my_friendly_assert (maxtype < typevec_size, 387); + typevec[maxtype++] = parmtype; + } + + if (last_type && same_type_p (parmtype, last_type)) + { + if (flag_do_squangling + || (old_style_repeats + && is_back_referenceable_type (parmtype))) + { + /* The next type is the same as this one. Keep + track of the repetition, and output the repeat + count later. */ + nrepeats++; + continue; + } + } + else if (nrepeats != 0) + { + /* Indicate how many times the previous parameter was + repeated. */ + if (old_style_repeats) + flush_repeats (nrepeats, last_type); + else + issue_nrepeats (nrepeats, last_type); + nrepeats = 0; + } + + last_type = parmtype; + + /* Note that for bug-compatibility with 2.7.2, we can't build up + repeats of types other than the most recent one. So we call + flush_repeats every round, if we get this far. */ + if (old_style_repeats && flush_repeats (0, parmtype)) + continue; + + /* Output the PARMTYPE. */ + build_mangled_name_for_type_with_Gcode (parmtype, 1); + } + + /* Output the repeat count for the last parameter, if + necessary. */ + if (nrepeats != 0) + { + if (old_style_repeats) + flush_repeats (nrepeats, last_type); + else + issue_nrepeats (nrepeats, last_type); + nrepeats = 0; + } + + if (!parmtypes) + /* The parameter list ends in an ellipsis. */ + OB_PUTC ('e'); + } + + if (end) + OB_FINISH (); + return (char *)obstack_base (&scratch_obstack); +} + +/* Emit modifiers such as constant, read-only, and volatile. */ + +static void +process_modifiers (parmtype) + tree parmtype; +{ + /* Note that here we do not use CP_TYPE_CONST_P and friends because + we describe types recursively; we will get the `const' in + `const int ()[10]' when processing the `const int' part. */ + if (TYPE_READONLY (parmtype)) + OB_PUTC ('C'); + if (TREE_CODE (parmtype) == INTEGER_TYPE + && parmtype != char_type_node + && parmtype != wchar_type_node + && (TYPE_MAIN_VARIANT (parmtype) + == unsigned_type (TYPE_MAIN_VARIANT (parmtype))) + && ! TYPE_FOR_JAVA (parmtype)) + OB_PUTC ('U'); + if (TYPE_VOLATILE (parmtype)) + OB_PUTC ('V'); + /* It would be better to use `R' for `restrict', but that's already + used for reference types. And `r' is used for `long double'. */ + if (TYPE_RESTRICT (parmtype)) + OB_PUTC ('u'); +} + +/* Check to see if TYPE has been entered into the Bcode typelist. If + so, return 1 and emit a backreference to TYPE. Otherwise, add TYPE + to the list of back-referenceable types and return 0. */ + +static int +check_btype (type) + tree type; +{ + int x; + + if (btypelist == NULL) + return 0; + + if (!is_back_referenceable_type (type)) + return 0; + + for (x = 0; x < maxbtype; x++) + if (same_type_p (type, btypelist[x])) + { + OB_PUTC ('B'); + icat (x); + if (x > 9) + OB_PUTC ('_'); + return 1 ; + } + + if (maxbsize <= maxbtype) + { + /* Enlarge the table. */ + maxbsize = maxbsize * 3 / 2; + btypelist = (tree *)xrealloc (btypelist, sizeof (tree) * maxbsize); + } + + /* Register the TYPE. */ + btypelist[maxbtype++] = type; + + return 0; +} + +/* Emit the correct code for various node types. */ + +static void +process_overload_item (parmtype, extra_Gcode) + tree parmtype; + int extra_Gcode; +{ + numeric_output_need_bar = 0; + + /* Our caller should have already handed any qualifiers, so pull out the + TYPE_MAIN_VARIANT to avoid typedef confusion. Except we can't do that + for arrays, because they are transparent to qualifiers. Sigh. */ + if (TREE_CODE (parmtype) == ARRAY_TYPE) + parmtype = canonical_type_variant (parmtype); + else + parmtype = TYPE_MAIN_VARIANT (parmtype); + + /* These tree types are considered modifiers for B code squangling, + and therefore should not get entries in the Btypelist. They are, + however, repeatable types. */ + + switch (TREE_CODE (parmtype)) + { + case REFERENCE_TYPE: + OB_PUTC ('R'); + goto more; + + case ARRAY_TYPE: +#if PARM_CAN_BE_ARRAY_TYPE + { + OB_PUTC ('A'); + if (TYPE_DOMAIN (parmtype) == NULL_TREE) + OB_PUTC ('_'); + else + { + tree length = array_type_nelts (parmtype); + if (TREE_CODE (length) != INTEGER_CST || flag_do_squangling) + { + length = fold (build (PLUS_EXPR, TREE_TYPE (length), + length, integer_one_node)); + STRIP_NOPS (length); + } + build_overload_value (sizetype, length, 1); + } + if (numeric_output_need_bar && ! flag_do_squangling) + OB_PUTC ('_'); + goto more; + } +#else + OB_PUTC ('P'); + goto more; +#endif + + case POINTER_TYPE: + /* Even though the vlist_type_node is PPPFe (i.e. `int + (***)(...)'), it is different from the any other occurence of + the pointer type, because the underlying function type is + different. */ + if (parmtype == vlist_type_node) + { + OB_PUTS (VLIST_TYPE_NAME); + return; + } + OB_PUTC ('P'); + more: + build_mangled_name_for_type (TREE_TYPE (parmtype)); + return; + break; + + default: + break; + } + + if (flag_do_squangling && check_btype (parmtype)) + /* If PARMTYPE is already in the list of back-referenceable types, + then check_btype will output the appropriate reference, and + there's nothing more to do. */ + return; + + switch (TREE_CODE (parmtype)) + { + case OFFSET_TYPE: + OB_PUTC ('O'); + build_mangled_name_for_type (TYPE_OFFSET_BASETYPE (parmtype)); + OB_PUTC ('_'); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + break; + + case FUNCTION_TYPE: + case METHOD_TYPE: + { + tree parms = TYPE_ARG_TYPES (parmtype); + + /* Rather than implementing a reentrant TYPEVEC, we turn off + repeat codes here, unless we're squangling. Squangling + doesn't make use of the TYPEVEC, so there's no reentrancy + problem. */ + int old_nofold = nofold; + if (!flag_do_squangling) + nofold = 1; + + if (TREE_CODE (parmtype) == METHOD_TYPE) + { + /* Mark this as a method. */ + OB_PUTC ('M'); + /* Output the class of which this method is a member. */ + build_mangled_name_for_type (TYPE_METHOD_BASETYPE (parmtype)); + /* Output any qualifiers for the `this' parameter. */ + process_modifiers (TREE_TYPE (TREE_VALUE (parms))); + } + + /* Output the parameter types. */ + OB_PUTC ('F'); + if (parms == NULL_TREE) + OB_PUTC ('e'); + else if (parms == void_list_node) + OB_PUTC ('v'); + else + build_mangled_name (parms, 0, 0); + + /* Output the return type. */ + OB_PUTC ('_'); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + + nofold = old_nofold; + break; + } + + case INTEGER_TYPE: + if (parmtype == integer_type_node + || parmtype == unsigned_type_node + || parmtype == java_int_type_node) + OB_PUTC ('i'); + else if (parmtype == long_integer_type_node + || parmtype == long_unsigned_type_node) + OB_PUTC ('l'); + else if (parmtype == short_integer_type_node + || parmtype == short_unsigned_type_node + || parmtype == java_short_type_node) + OB_PUTC ('s'); + else if (parmtype == signed_char_type_node) + { + OB_PUTC ('S'); + OB_PUTC ('c'); + } + else if (parmtype == char_type_node + || parmtype == unsigned_char_type_node + || parmtype == java_byte_type_node) + OB_PUTC ('c'); + else if (parmtype == wchar_type_node + || parmtype == java_char_type_node) + OB_PUTC ('w'); + else if (parmtype == long_long_integer_type_node + || parmtype == long_long_unsigned_type_node + || parmtype == java_long_type_node) + OB_PUTC ('x'); + else if (parmtype == java_boolean_type_node) + OB_PUTC ('b'); +#if HOST_BITS_PER_WIDE_INT >= 64 + else if (parmtype == intTI_type_node + || parmtype == unsigned_intTI_type_node) + { + /* Should just check a flag here instead of specific + *_type_nodes, because all C9x types could use this. */ + int bits = TREE_INT_CST_LOW (TYPE_SIZE (parmtype)); + build_mangled_C9x_name (bits); + } +#endif + else + my_friendly_abort (73); + break; + + case BOOLEAN_TYPE: + OB_PUTC ('b'); + break; + + case REAL_TYPE: + if (parmtype == long_double_type_node) + OB_PUTC ('r'); + else if (parmtype == double_type_node + || parmtype == java_double_type_node) + OB_PUTC ('d'); + else if (parmtype == float_type_node + || parmtype == java_float_type_node) + OB_PUTC ('f'); + else my_friendly_abort (74); + break; + + case COMPLEX_TYPE: + OB_PUTC ('J'); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + break; + + case VOID_TYPE: + OB_PUTC ('v'); + break; + + case ERROR_MARK: /* not right, but nothing is anyway */ + break; + + /* have to do these */ + case UNION_TYPE: + case RECORD_TYPE: + { + if (extra_Gcode) + OB_PUTC ('G'); /* make it look incompatible with AT&T */ + /* drop through into next case */ + } + case ENUMERAL_TYPE: + { + tree name = TYPE_NAME (parmtype); + + my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 248); + + build_qualified_name (name); + break; + } + + case UNKNOWN_TYPE: + /* This will take some work. */ + OB_PUTC ('?'); + break; + + case TEMPLATE_TEMPLATE_PARM: + /* Find and output the original template parameter + declaration. */ + if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parmtype)) + { + build_mangled_template_parm_index ("tzX", + TEMPLATE_TYPE_PARM_INDEX + (parmtype)); + build_template_parm_names + (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (parmtype)), + TYPE_TI_ARGS (parmtype)); + } + else + { + build_mangled_template_parm_index ("ZzX", + TEMPLATE_TYPE_PARM_INDEX + (parmtype)); + build_template_template_parm_names + (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype))); + } + break; + + case TEMPLATE_TYPE_PARM: + build_mangled_template_parm_index ("X", + TEMPLATE_TYPE_PARM_INDEX + (parmtype)); + break; + + case TYPENAME_TYPE: + /* When mangling the type of a function template whose + declaration looks like: + + template void foo(typename T::U) + + we have to mangle these. */ + build_qualified_name (parmtype); + break; + + default: + my_friendly_abort (75); + } + +} + +/* Produce the mangling for a variable named NAME in CONTEXT, which can + be either a class TYPE or a FUNCTION_DECL. */ + +tree +build_static_name (context, name) + tree context, name; +{ + OB_INIT (); + numeric_output_need_bar = 0; + start_squangling (); +#ifdef JOINER + OB_PUTC ('_'); + build_qualified_name (context); + OB_PUTC (JOINER); +#else + OB_PUTS ("__static_"); + build_qualified_name (context); + OB_PUTC ('_'); +#endif + OB_PUTID (name); + OB_FINISH (); + end_squangling (); + + return get_identifier ((char *)obstack_base (&scratch_obstack)); +} + +/* FOR_METHOD should be 1 if the declaration in question is for a member + of a class (including a static member) and 2 if the declaration is + for a constructor. */ +tree +build_decl_overload_real (dname, parms, ret_type, tparms, targs, + for_method) + tree dname; + tree parms; + tree ret_type; + tree tparms; + tree targs; + int for_method; +{ + char *name = IDENTIFIER_POINTER (dname); + + /* member operators new and delete look like methods at this point. */ + if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST + && TREE_CHAIN (parms) == void_list_node) + { + if (dname == ansi_opname[(int) DELETE_EXPR]) + return get_identifier ("__builtin_delete"); + else if (dname == ansi_opname[(int) VEC_DELETE_EXPR]) + return get_identifier ("__builtin_vec_delete"); + if (dname == ansi_opname[(int) NEW_EXPR]) + return get_identifier ("__builtin_new"); + else if (dname == ansi_opname[(int) VEC_NEW_EXPR]) + return get_identifier ("__builtin_vec_new"); + } + + start_squangling (); + OB_INIT (); + if (for_method != 2) + OB_PUTCP (name); + /* Otherwise, we can divine that this is a constructor, + and figure out its name without any extra encoding. */ + + OB_PUTC2 ('_', '_'); + numeric_output_need_bar = 0; + + if (tparms) + { + OB_PUTC ('H'); + build_template_parm_names (tparms, targs); + OB_PUTC ('_'); + } + else if (!for_method && current_namespace == global_namespace) + /* XXX this works only if we call this in the same namespace + as the declaration. Unfortunately, we don't have the _DECL, + only its name */ + OB_PUTC ('F'); + + if (!for_method && current_namespace != global_namespace) + /* qualify with namespace */ + build_qualified_name (current_namespace); + + if (parms == NULL_TREE) + OB_PUTC ('e'); + else if (parms == void_list_node) + OB_PUTC ('v'); + else + { + if (!flag_do_squangling) + { + /* Allocate typevec array. */ + maxtype = 0; + typevec_size = list_length (parms); + if (!for_method && current_namespace != global_namespace) + /* The namespace of a global function needs one slot. */ + typevec_size++; + typevec = (tree *)alloca (typevec_size * sizeof (tree)); + } + nofold = 0; + + if (for_method) + { + tree this_type = TREE_VALUE (parms); + + if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */ + this_type = SIGNATURE_TYPE (this_type); + else + this_type = TREE_TYPE (this_type); + + build_mangled_name_for_type (this_type); + + if (!flag_do_squangling) + { + my_friendly_assert (maxtype < typevec_size, 387); + typevec[maxtype++] = this_type; + } + + if (TREE_CHAIN (parms)) + build_mangled_name (TREE_CHAIN (parms), 0, 0); + else + OB_PUTC ('e'); + } + else + { + /* the namespace qualifier for a global function + will count as type */ + if (current_namespace != global_namespace + && !flag_do_squangling) + { + my_friendly_assert (maxtype < typevec_size, 387); + typevec[maxtype++] = current_namespace; + } + build_mangled_name (parms, 0, 0); + } + + if (!flag_do_squangling) + /* Deallocate typevec array. */ + typevec = NULL; + } + + if (ret_type != NULL_TREE && for_method != 2) + { + /* Add the return type. */ + OB_PUTC ('_'); + build_mangled_name_for_type (ret_type); + } + + OB_FINISH (); + end_squangling (); + { + tree n = get_identifier (obstack_base (&scratch_obstack)); + if (IDENTIFIER_OPNAME_P (dname)) + IDENTIFIER_OPNAME_P (n) = 1; + return n; + } +} + +/* Change the name of a function definition so that it may be + overloaded. NAME is the name of the function to overload, + PARMS is the parameter list (which determines what name the + final function obtains). + + FOR_METHOD is 1 if this overload is being performed + for a method, rather than a function type. It is 2 if + this overload is being performed for a constructor. */ + +tree +build_decl_overload (dname, parms, for_method) + tree dname; + tree parms; + int for_method; +{ + return build_decl_overload_real (dname, parms, NULL_TREE, NULL_TREE, + NULL_TREE, for_method); +} + +/* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */ + +void +set_mangled_name_for_decl (decl) + tree 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 = + hash_tree_chain (build_pointer_type (DECL_CLASS_CONTEXT (decl)), + parm_types); + else + /* The only member functions whose type is a FUNCTION_TYPE, rather + than a METHOD_TYPE, should be static members. */ + my_friendly_assert (!DECL_CONTEXT (decl) + || !IS_AGGR_TYPE_CODE (TREE_CODE (DECL_CONTEXT (decl))) + || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE, + 0); + + DECL_ASSEMBLER_NAME (decl) + = build_decl_overload (DECL_NAME (decl), parm_types, + DECL_FUNCTION_MEMBER_P (decl) + + DECL_CONSTRUCTOR_P (decl)); +} + +/* Build an overload name for the type expression TYPE. */ + +tree +build_typename_overload (type) + tree type; +{ + tree id; + + OB_INIT (); + OB_PUTID (ansi_opname[(int) TYPE_EXPR]); + nofold = 1; + start_squangling (); + build_mangled_name (type, 0, 1); + id = get_identifier (obstack_base (&scratch_obstack)); + IDENTIFIER_OPNAME_P (id) = 1; +#if 0 + IDENTIFIER_GLOBAL_VALUE (id) = TYPE_MAIN_DECL (type); +#endif + TREE_TYPE (id) = type; + end_squangling (); + return id; +} + +tree +build_overload_with_type (name, type) + tree name, type; +{ + OB_INIT (); + OB_PUTID (name); + nofold = 1; + + start_squangling (); + build_mangled_name (type, 0, 1); + end_squangling (); + return get_identifier (obstack_base (&scratch_obstack)); +} + +tree +get_id_2 (name, name2) + char *name; + tree name2; +{ + OB_INIT (); + OB_PUTCP (name); + OB_PUTID (name2); + OB_FINISH (); + return get_identifier (obstack_base (&scratch_obstack)); +} + +/* Print a binfo path T, starting with the most derived class. If + OMIT_LAST is set, drop and return the most derived class. */ + +static tree +build_base_path (t, omit_last) + tree t; + int omit_last; +{ + tree ret = NULL_TREE; + if (BINFO_INHERITANCE_CHAIN (t)) + ret = build_base_path (BINFO_INHERITANCE_CHAIN (t), omit_last); + else if (omit_last) + return t; + process_overload_item (BINFO_TYPE (t), 0); + return ret; +} + +/* Return a mangled name for a vlist vtable, using the path of both + BASE and VBASE. */ + +tree +get_vlist_vtable_id (base, vbase) + tree base, vbase; +{ + tree last; + OB_INIT (); + OB_PUTS (VCTABLE_NAME); + build_base_path (base, 0); + OB_PUTC ('_'); + /* Since the base path should end where the vbase path starts, we + can omit the most-derived class in the vbase path. Check below + that this really happens. */ + last = build_base_path (vbase, 1); + my_friendly_assert (BINFO_TYPE (last) == BINFO_TYPE (base), 990402); + OB_FINISH (); + return get_identifier (obstack_base (&scratch_obstack)); +} + +/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. If + HAS_VLIST is set, also add the vlist argument. */ + +tree +build_destructor_name (type, has_vlist) + tree type; + int has_vlist; +{ + OB_INIT (); + OB_PUTS (DESTRUCTOR_DECL_PREFIX); + start_squangling (); + build_mangled_name_for_type (type); + /* If we need backwards compatibility, we can get aways by + not linking type-safely, as the dtor will check whether + the argument was provided. */ + if (has_vlist && !flag_vtable_thunks_compat) + OB_PUTS (VLIST_TYPE_NAME); + OB_FINISH (); + end_squangling (); + return get_identifier (obstack_base (&scratch_obstack)); +} + +/* Given a tree_code CODE, and some arguments (at least one), + attempt to use an overloaded operator on the arguments. + + For unary operators, only the first argument need be checked. + For binary operators, both arguments may need to be checked. + + Member functions can convert class references to class pointers, + for one-level deep indirection. More than that is not supported. + Operators [](), ()(), and ->() must be member functions. + + We call function call building calls with LOOKUP_COMPLAIN if they + are our only hope. This is true when we see a vanilla operator + applied to something of aggregate type. If this fails, we are free + to return `error_mark_node', because we will have reported the + error. + + Operators NEW and DELETE overload in funny ways: operator new takes + a single `size' parameter, and operator delete takes a pointer to the + storage being deleted. When overloading these operators, success is + assumed. If there is a failure, report an error message and return + `error_mark_node'. */ + +/* NOSTRICT */ +tree +build_opfncall (code, flags, xarg1, xarg2, arg3) + enum tree_code code; + int flags; + tree xarg1, xarg2, arg3; +{ + return build_new_op (code, flags, xarg1, xarg2, arg3); +} + +/* This function takes an identifier, ID, and attempts to figure out what + it means. There are a number of possible scenarios, presented in increasing + order of hair: + + 1) not in a class's scope + 2) in class's scope, member name of the class's method + 3) in class's scope, but not a member name of the class + 4) in class's scope, member name of a class's variable + + NAME is $1 from the bison rule. It is an IDENTIFIER_NODE. + VALUE is $$ from the bison rule. It is the value returned by lookup_name ($1) + + As a last ditch, try to look up the name as a label and return that + address. + + Values which are declared as being of REFERENCE_TYPE are + automatically dereferenced here (as a hack to make the + compiler faster). */ + +tree +hack_identifier (value, name) + tree value, name; +{ + tree type; + + if (value == error_mark_node) + { + if (current_class_name) + { + tree fields = lookup_fnfields (TYPE_BINFO (current_class_type), name, 1); + if (fields == error_mark_node) + return error_mark_node; + if (fields) + { + tree fndecl; + + fndecl = TREE_VALUE (fields); + my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251); + /* I could not trigger this code. MvL */ + my_friendly_abort (980325); +#ifdef DEAD + if (DECL_CHAIN (fndecl) == NULL_TREE) + { + warning ("methods cannot be converted to function pointers"); + return fndecl; + } + else + { + error ("ambiguous request for method pointer `%s'", + IDENTIFIER_POINTER (name)); + return error_mark_node; + } +#endif + } + } + if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name)) + { + return IDENTIFIER_LABEL_VALUE (name); + } + return error_mark_node; + } + + type = TREE_TYPE (value); + if (TREE_CODE (value) == FIELD_DECL) + { + if (current_class_ptr == NULL_TREE) + { + if (current_function_decl + && DECL_STATIC_FUNCTION_P (current_function_decl)) + cp_error ("invalid use of member `%D' in static member function", + value); + else + /* We can get here when processing a bad default + argument, like: + struct S { int a; void f(int i = a); } */ + cp_error ("invalid use of member `%D'", value); + + return error_mark_node; + } + TREE_USED (current_class_ptr) = 1; + + /* Mark so that if we are in a constructor, and then find that + this field was initialized by a base initializer, + we can emit an error message. */ + TREE_USED (value) = 1; + value = build_component_ref (current_class_ref, name, NULL_TREE, 1); + } + else if ((TREE_CODE (value) == FUNCTION_DECL + && DECL_FUNCTION_MEMBER_P (value)) + || (TREE_CODE (value) == OVERLOAD + && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (value)))) + { + tree decl; + + if (TREE_CODE (value) == OVERLOAD) + value = OVL_CURRENT (value); + + if (IS_SIGNATURE (DECL_CLASS_CONTEXT (value))) + return value; + + decl = maybe_dummy_object (DECL_CLASS_CONTEXT (value), 0); + value = build_component_ref (decl, name, NULL_TREE, 1); + } + else if (really_overloaded_fn (value)) + ; + else if (TREE_CODE (value) == OVERLOAD) + /* not really overloaded function */ + mark_used (OVL_FUNCTION (value)); + else if (TREE_CODE (value) == TREE_LIST) + { + /* Ambiguous reference to base members, possibly other cases?. */ + tree t = value; + while (t && TREE_CODE (t) == TREE_LIST) + { + mark_used (TREE_VALUE (t)); + t = TREE_CHAIN (t); + } + } + else if (TREE_CODE (value) == NAMESPACE_DECL) + { + cp_error ("use of namespace `%D' as expression", value); + return error_mark_node; + } + else if (DECL_CLASS_TEMPLATE_P (value)) + { + cp_error ("use of class template `%T' as expression", value); + return error_mark_node; + } + else + mark_used (value); + + if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL + || TREE_CODE (value) == RESULT_DECL) + { + tree context = decl_function_context (value); + if (context != NULL_TREE && context != current_function_decl + && ! TREE_STATIC (value)) + { + cp_error ("use of %s from containing function", + (TREE_CODE (value) == VAR_DECL + ? "`auto' variable" : "parameter")); + cp_error_at (" `%#D' declared here", value); + value = error_mark_node; + } + } + + if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value)) + { + if (DECL_LANG_SPECIFIC (value) + && DECL_CLASS_CONTEXT (value) != current_class_type) + { + tree path; + register tree context + = (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value)) + ? DECL_CLASS_CONTEXT (value) + : DECL_CONTEXT (value); + + get_base_distance (context, current_class_type, 0, &path); + if (path && !enforce_access (current_class_type, value)) + return error_mark_node; + } + } + else if (TREE_CODE (value) == TREE_LIST + && TREE_TYPE (value) == error_mark_node) + { + error ("request for member `%s' is ambiguous in multiple inheritance lattice", + IDENTIFIER_POINTER (name)); + print_candidates (value); + return error_mark_node; + } + + if (! processing_template_decl) + value = convert_from_reference (value); + return value; +} + + +tree +make_thunk (function, delta) + tree function; + int delta; +{ + tree thunk_id; + tree thunk; + tree func_decl; + + if (TREE_CODE (function) != ADDR_EXPR) + abort (); + func_decl = TREE_OPERAND (function, 0); + if (TREE_CODE (func_decl) != FUNCTION_DECL) + abort (); + + OB_INIT (); + OB_PUTS ("__thunk_"); + if (delta > 0) + { + OB_PUTC ('n'); + icat (delta); + } + else + icat (-delta); + OB_PUTC ('_'); + OB_PUTID (DECL_ASSEMBLER_NAME (func_decl)); + OB_FINISH (); + thunk_id = get_identifier (obstack_base (&scratch_obstack)); + + thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); + if (thunk && TREE_CODE (thunk) != THUNK_DECL) + { + cp_error ("implementation-reserved name `%D' used", thunk_id); + thunk = NULL_TREE; + SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk); + } + if (thunk == NULL_TREE) + { + thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl)); + TREE_READONLY (thunk) = TREE_READONLY (func_decl); + TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl); + comdat_linkage (thunk); + TREE_SET_CODE (thunk, THUNK_DECL); + DECL_INITIAL (thunk) = function; + THUNK_DELTA (thunk) = delta; + DECL_EXTERNAL (thunk) = 1; + DECL_ARTIFICIAL (thunk) = 1; + /* So that finish_file can write out any thunks that need to be: */ + pushdecl_top_level (thunk); + } + return thunk; +} + +/* Emit the definition of a C++ multiple inheritance vtable thunk. */ + +void +emit_thunk (thunk_fndecl) + tree thunk_fndecl; +{ + tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0); + int delta = THUNK_DELTA (thunk_fndecl); + + if (TREE_ASM_WRITTEN (thunk_fndecl)) + return; + + TREE_ASM_WRITTEN (thunk_fndecl) = 1; + + TREE_ADDRESSABLE (function) = 1; + mark_used (function); + + if (current_function_decl) + abort (); + + TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL); + + { +#ifdef ASM_OUTPUT_MI_THUNK + char *fnname; + current_function_decl = thunk_fndecl; + /* Make sure we build up its RTL before we go onto the + temporary obstack. */ + make_function_rtl (thunk_fndecl); + temporary_allocation (); + DECL_RESULT (thunk_fndecl) + = build_decl (RESULT_DECL, 0, integer_type_node); + fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); + init_function_start (thunk_fndecl, input_filename, lineno); + current_function_is_thunk = 1; + assemble_start_function (thunk_fndecl, fnname); + ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function); + assemble_end_function (thunk_fndecl, fnname); + permanent_allocation (1); + current_function_decl = 0; +#else /* ASM_OUTPUT_MI_THUNK */ + /* If we don't have the necessary macro for efficient thunks, generate a + thunk function that just makes a call to the real function. + Unfortunately, this doesn't work for varargs. */ + + tree a, t; + + if (varargs_function_p (function)) + cp_error ("generic thunk code fails for method `%#D' which uses `...'", + function); + + /* Set up clone argument trees for the thunk. */ + t = NULL_TREE; + for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) + { + tree x = copy_node (a); + TREE_CHAIN (x) = t; + DECL_CONTEXT (x) = thunk_fndecl; + t = x; + } + a = nreverse (t); + DECL_ARGUMENTS (thunk_fndecl) = a; + DECL_RESULT (thunk_fndecl) = NULL_TREE; + DECL_LANG_SPECIFIC (thunk_fndecl) = DECL_LANG_SPECIFIC (function); + copy_lang_decl (thunk_fndecl); + DECL_INTERFACE_KNOWN (thunk_fndecl) = 1; + DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1; + + start_function (NULL_TREE, thunk_fndecl, NULL_TREE, 1); + store_parm_decls (); + current_function_is_thunk = 1; + + /* Build up the call to the real function. */ + t = build_int_2 (delta, -1 * (delta < 0)); + TREE_TYPE (t) = signed_type (sizetype); + t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t)); + t = expr_tree_cons (NULL_TREE, t, NULL_TREE); + for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) + t = expr_tree_cons (NULL_TREE, a, t); + t = nreverse (t); + t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t); + c_expand_return (t); + + finish_function (lineno, 0, 0); + + /* Don't let the backend defer this function. */ + if (DECL_DEFER_OUTPUT (thunk_fndecl)) + { + output_inline_function (thunk_fndecl); + permanent_allocation (1); + } +#endif /* ASM_OUTPUT_MI_THUNK */ + } + + TREE_SET_CODE (thunk_fndecl, THUNK_DECL); +} + +void +make_vlist_ctor_wrapper (fn) + tree fn; +{ + tree fntype, decl; + tree arg_types, parms, parm, basetype, pbasetype; + tree t, ctors; + + arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); + pbasetype = TREE_VALUE (arg_types); + basetype = TREE_TYPE (pbasetype); + parms = DECL_ARGUMENTS (fn); + + /* Skip this, __in_chrg, and _vlist */ + arg_types = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_types))); + + + /* Add __in_charge. */ + arg_types = hash_tree_chain (integer_type_node, arg_types); + + /* Don't add this to arg_types, as build_cplus_method_type does so. */ + + fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), + arg_types); + + decl = build_lang_decl (FUNCTION_DECL, DECL_NAME (fn), fntype); + DECL_LANG_SPECIFIC (decl)->decl_flags = DECL_LANG_SPECIFIC (fn)->decl_flags; + DECL_EXTERNAL (decl) = 0; + TREE_PUBLIC (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + DECL_CONSTRUCTOR_P (decl) = 1; + DECL_CONSTRUCTOR_FOR_VBASE (decl) = CONSTRUCTOR_FOR_VBASE; + /* Claim that this is never a template instantiation. */ + DECL_USE_TEMPLATE (decl) = 0; + DECL_TEMPLATE_INFO (decl) = NULL_TREE; + + /* Set up clone argument trees for the thunk. */ + parms = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (parms))); + /* Add this */ + t = build_decl (PARM_DECL, this_identifier, pbasetype); + SET_DECL_ARTIFICIAL (t); + DECL_ARG_TYPE (t) = pbasetype; + DECL_REGISTER (t) = 1; + /* Add __in_charge. */ + parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); + SET_DECL_ARTIFICIAL (parm); + DECL_ARG_TYPE (parm) = integer_type_node; + TREE_CHAIN (parm) = t; + t = parm; + + while (parms) + { + tree x = copy_node (parms); + TREE_CHAIN (x) = t; + DECL_CONTEXT (x) = decl; + t = x; + parms = TREE_CHAIN (parms); + } + parms = nreverse (t); + DECL_ARGUMENTS (decl) = parms; + + DECL_ASSEMBLER_NAME (decl) + = build_decl_overload (DECL_NAME (decl), + TYPE_ARG_TYPES (TREE_TYPE (decl)), 2); + + ctors = CLASSTYPE_METHOD_VEC (basetype); + if (ctors) + ctors = TREE_VEC_ELT (ctors, 0); + for ( ; ctors; ctors = OVL_NEXT (ctors)) + if (DECL_ASSEMBLER_NAME (OVL_CURRENT (ctors)) + == DECL_ASSEMBLER_NAME (decl)) + break; + + if (!ctors) + { + add_method (basetype, 0, decl); + cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0, 0); + } + else + decl = OVL_CURRENT (ctors); + + /* Remember the original function. */ + DECL_VLIST_CTOR_WRAPPED (decl) = fn; + + /* When fn is declared, DECL_INITIAL is null. When it is defined, + DECL_INITIAL will be error_mark_node. */ + if (DECL_INITIAL (fn) == error_mark_node) + { + /* Record that the ctor is being defined, so we also emit the + wrapper later. */ + TREE_USED (decl) = 1; + DECL_NOT_REALLY_EXTERN (decl) = 1; + DECL_INITIAL (decl) = NULL_TREE; + mark_inline_for_output (decl); + } +} + +static void +emit_vlist_ctor_wrapper (decl) + tree decl; +{ + tree t, parms, fn; + + current_function_is_thunk = 1; + + parms = DECL_ARGUMENTS (decl); + fn = DECL_VLIST_CTOR_WRAPPED (decl); + mark_used (fn); + + /* Build up the call to the real function. */ + t = NULL_TREE; + /* Push this, __in_charge. */ + t = expr_tree_cons (NULL_TREE, parms, t); + parms = TREE_CHAIN (parms); + t = expr_tree_cons (NULL_TREE, parms, t); + parms = TREE_CHAIN (parms); + /* Push 0 as __vlist. */ + t = expr_tree_cons (NULL_TREE, vlist_zero_node, t); + /* Push rest of arguments. */ + while (parms) + { + t = expr_tree_cons (NULL_TREE, parms, t); + parms = TREE_CHAIN (parms); + } + t = nreverse (t); + t = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), t); + expand_expr_stmt (t); +} + + +/* Code for synthesizing methods which have default semantics defined. */ + +/* For the anonymous union in TYPE, return the member that is at least as + large as the rest of the members, so we can copy it. */ + +static tree +largest_union_member (type) + tree type; +{ + tree f, type_size = TYPE_SIZE (type); + + for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f)) + if (simple_cst_equal (DECL_SIZE (f), type_size) == 1) + return f; + + /* We should always find one. */ + my_friendly_abort (323); + return NULL_TREE; +} + +/* Generate code for default X(X&) constructor. */ + +static void +do_build_copy_constructor (fndecl) + tree fndecl; +{ + tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); + tree t; + + clear_last_expr (); + push_momentary (); + + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + parm = TREE_CHAIN (parm); + if (TYPE_USES_PVBASES (current_class_type)) + parm = TREE_CHAIN (parm); + parm = convert_from_reference (parm); + + if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) + && is_empty_class (current_class_type)) + /* Don't copy the padding byte; it might not have been allocated + if *this is a base subobject. */; + else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) + { + t = build (INIT_EXPR, void_type_node, current_class_ref, parm); + TREE_SIDE_EFFECTS (t) = 1; + cplus_expand_expr_stmt (t); + } + else + { + tree fields = TYPE_FIELDS (current_class_type); + int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); + tree binfos = TYPE_BINFO_BASETYPES (current_class_type); + int i; + + /* Initialize all the base-classes. */ + for (t = CLASSTYPE_VBASECLASSES (current_class_type); t; + t = TREE_CHAIN (t)) + current_base_init_list + = tree_cons (BINFO_TYPE (t), parm, current_base_init_list); + for (i = 0; i < n_bases; ++i) + { + t = TREE_VEC_ELT (binfos, i); + if (TREE_VIA_VIRTUAL (t)) + continue; + + current_base_init_list + = tree_cons (BINFO_TYPE (t), parm, current_base_init_list); + } + + for (; fields; fields = TREE_CHAIN (fields)) + { + tree init, t; + tree field = fields; + + if (TREE_CODE (field) != FIELD_DECL) + continue; + + init = parm; + if (DECL_NAME (field)) + { + if (VFIELD_NAME_P (DECL_NAME (field))) + continue; + if (VBASE_NAME_P (DECL_NAME (field))) + continue; + + /* True for duplicate members. */ + if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) + continue; + } + else if ((t = TREE_TYPE (field)) != NULL_TREE + && ANON_UNION_TYPE_P (t) + && TYPE_FIELDS (t) != NULL_TREE) + { + do + { + init = build (COMPONENT_REF, t, init, field); + field = largest_union_member (t); + } + while ((t = TREE_TYPE (field)) != NULL_TREE + && ANON_UNION_TYPE_P (t) + && TYPE_FIELDS (t) != NULL_TREE); + } + else + continue; + + init = build (COMPONENT_REF, TREE_TYPE (field), init, field); + init = build_tree_list (NULL_TREE, init); + + current_member_init_list + = tree_cons (DECL_NAME (field), init, current_member_init_list); + } + current_member_init_list = nreverse (current_member_init_list); + current_base_init_list = nreverse (current_base_init_list); + setup_vtbl_ptr (); + } + + pop_momentary (); +} + +static void +do_build_assign_ref (fndecl) + tree fndecl; +{ + tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); + + clear_last_expr (); + push_momentary (); + + parm = convert_from_reference (parm); + + if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) + && is_empty_class (current_class_type)) + /* Don't copy the padding byte; it might not have been allocated + if *this is a base subobject. */; + else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) + { + tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm); + TREE_SIDE_EFFECTS (t) = 1; + cplus_expand_expr_stmt (t); + } + else + { + tree fields = TYPE_FIELDS (current_class_type); + int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); + tree binfos = TYPE_BINFO_BASETYPES (current_class_type); + int i; + + for (i = 0; i < n_bases; ++i) + { + tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); + tree p = convert_to_reference + (build_reference_type (basetype), parm, + CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); + p = convert_from_reference (p); + p = build_member_call (basetype, ansi_opname [MODIFY_EXPR], + build_expr_list (NULL_TREE, p)); + expand_expr_stmt (p); + } + for (; fields; fields = TREE_CHAIN (fields)) + { + tree comp, init, t; + tree field = fields; + + if (TREE_CODE (field) != FIELD_DECL) + continue; + + if (CP_TYPE_CONST_P (TREE_TYPE (field))) + { + if (DECL_NAME (field)) + cp_error ("non-static const member `%#D', can't use default assignment operator", field); + else + cp_error ("non-static const member in type `%T', can't use default assignment operator", current_class_type); + continue; + } + else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) + { + if (DECL_NAME (field)) + cp_error ("non-static reference member `%#D', can't use default assignment operator", field); + else + cp_error ("non-static reference member in type `%T', can't use default assignment operator", current_class_type); + continue; + } + + comp = current_class_ref; + init = parm; + + if (DECL_NAME (field)) + { + if (VFIELD_NAME_P (DECL_NAME (field))) + continue; + if (VBASE_NAME_P (DECL_NAME (field))) + continue; + + /* True for duplicate members. */ + if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) + continue; + } + else if ((t = TREE_TYPE (field)) != NULL_TREE + && ANON_UNION_TYPE_P (t) + && TYPE_FIELDS (t) != NULL_TREE) + { + do + { + comp = build (COMPONENT_REF, t, comp, field); + init = build (COMPONENT_REF, t, init, field); + field = largest_union_member (t); + } + while ((t = TREE_TYPE (field)) != NULL_TREE + && ANON_UNION_TYPE_P (t) + && TYPE_FIELDS (t) != NULL_TREE); + } + else + continue; + + comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field); + init = build (COMPONENT_REF, TREE_TYPE (field), init, field); + + expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); + } + } + c_expand_return (current_class_ref); + pop_momentary (); +} + +void +synthesize_method (fndecl) + tree fndecl; +{ + int nested = (current_function_decl != NULL_TREE); + tree context = hack_decl_function_context (fndecl); + + /* If this is a wrapper around a undefined vlist ctor, don't emit it + even if it is used. */ + if (DECL_VLIST_CTOR_WRAPPER_P (fndecl)) + { + tree orig_fn = DECL_VLIST_CTOR_WRAPPED (fndecl); + mark_used (orig_fn); + if (DECL_INITIAL (orig_fn) == NULL_TREE) + return; + } + + if (at_eof) + import_export_decl (fndecl); + + if (! context) + push_to_top_level (); + else if (nested) + push_cp_function_context (context); + + interface_unknown = 1; + start_function (NULL_TREE, fndecl, NULL_TREE, 1); + store_parm_decls (); + + if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR]) + do_build_assign_ref (fndecl); + else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) + ; + else + { + tree arg_chain = FUNCTION_ARG_CHAIN (fndecl); + if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl)) + arg_chain = TREE_CHAIN (arg_chain); + else if (DECL_CONSTRUCTOR_FOR_PVBASE_P (fndecl)) + arg_chain = TREE_CHAIN (TREE_CHAIN (arg_chain)); + if (DECL_VLIST_CTOR_WRAPPER_P (fndecl)) + emit_vlist_ctor_wrapper (fndecl); + else if (arg_chain != void_list_node) + do_build_copy_constructor (fndecl); + else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) + setup_vtbl_ptr (); + } + + finish_function (lineno, 0, nested); + + extract_interface_info (); + if (! context) + pop_from_top_level (); + else if (nested) + pop_cp_function_context (context); +} + + + Property changes on: vendor/gcc/2.95-20000526/contrib/gcc/cp/method.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/gcc/2.95-20000526/contrib/gcc/cp/pt.c =================================================================== --- vendor/gcc/2.95-20000526/contrib/gcc/cp/pt.c (nonexistent) +++ vendor/gcc/2.95-20000526/contrib/gcc/cp/pt.c (revision 60969) @@ -0,0 +1,9876 @@ +/* Handle parameterized types (templates) for GNU C++. + Copyright (C) 1992, 93-97, 1998, 1999 Free Software Foundation, Inc. + Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing. + Rewritten by Jason Merrill (jason@cygnus.com). + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Known bugs or deficiencies include: + + all methods must be provided in header files; can't use a source + file that contains only the method templates and "just win". */ + +#include "config.h" +#include "system.h" +#include "obstack.h" + +#include "tree.h" +#include "flags.h" +#include "cp-tree.h" +#include "decl.h" +#include "parse.h" +#include "lex.h" +#include "output.h" +#include "defaults.h" +#include "except.h" +#include "toplev.h" +#include "rtl.h" +#include "varray.h" + +/* The type of functions taking a tree, and some additional data, and + returning an int. */ +typedef int (*tree_fn_t) PROTO((tree, void*)); + +extern struct obstack permanent_obstack; + +extern int lineno; +extern char *input_filename; + +tree current_template_parms; +HOST_WIDE_INT processing_template_decl; + +/* The PENDING_TEMPLATES is a TREE_LIST of templates whose + instantiations have been deferred, either because their definitions + were not yet available, or because we were putting off doing the + work. The TREE_PURPOSE of each entry is a SRCLOC indicating where + the instantiate request occurred; the TREE_VALUE is a either a DECL + (for a function or static data member), or a TYPE (for a class) + indicating what we are hoping to instantiate. */ +static tree pending_templates; +static tree *template_tail = &pending_templates; + +static tree maybe_templates; +static tree *maybe_template_tail = &maybe_templates; + +int minimal_parse_mode; + +int processing_specialization; +int processing_explicit_instantiation; +int processing_template_parmlist; +static int template_header_count; + +static tree saved_trees; +static varray_type inline_parm_levels; +static size_t inline_parm_levels_used; + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +#define UNIFY_ALLOW_NONE 0 +#define UNIFY_ALLOW_MORE_CV_QUAL 1 +#define UNIFY_ALLOW_LESS_CV_QUAL 2 +#define UNIFY_ALLOW_DERIVED 4 +#define UNIFY_ALLOW_INTEGER 8 + +#define GTB_VIA_VIRTUAL 1 /* The base class we are examining is + virtual, or a base class of a virtual + base. */ +#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current + type with the desired type. */ + +static int resolve_overloaded_unification PROTO((tree, tree, tree, tree, + unification_kind_t, int)); +static int try_one_overload PROTO((tree, tree, tree, tree, tree, + unification_kind_t, int)); +static int unify PROTO((tree, tree, tree, tree, int)); +static void add_pending_template PROTO((tree)); +static int push_tinst_level PROTO((tree)); +static tree classtype_mangled_name PROTO((tree)); +static char *mangle_class_name_for_template PROTO((char *, tree, tree)); +static tree tsubst_expr_values PROTO((tree, tree)); +static int list_eq PROTO((tree, tree)); +static tree get_class_bindings PROTO((tree, tree, tree)); +static tree coerce_template_parms PROTO((tree, tree, tree, int, int)); +static void tsubst_enum PROTO((tree, tree, tree)); +static tree add_to_template_args PROTO((tree, tree)); +static tree add_outermost_template_args PROTO((tree, tree)); +static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*, + tree*)); +static int type_unification_real PROTO((tree, tree, tree, tree, + int, unification_kind_t, int)); +static void note_template_header PROTO((int)); +static tree maybe_fold_nontype_arg PROTO((tree)); +static tree convert_nontype_argument PROTO((tree, tree)); +static tree convert_template_argument PROTO ((tree, tree, tree, int, + int , tree)); +static tree get_bindings_overload PROTO((tree, tree, tree)); +static int for_each_template_parm PROTO((tree, tree_fn_t, void*)); +static tree build_template_parm_index PROTO((int, int, int, tree, tree)); +static int inline_needs_template_parms PROTO((tree)); +static void push_inline_template_parms_recursive PROTO((tree, int)); +static tree retrieve_specialization PROTO((tree, tree)); +static tree register_specialization PROTO((tree, tree, tree)); +static int unregister_specialization PROTO((tree, tree)); +static tree reduce_template_parm_level PROTO((tree, tree, int)); +static tree build_template_decl PROTO((tree, tree)); +static int mark_template_parm PROTO((tree, void *)); +static tree tsubst_friend_function PROTO((tree, tree)); +static tree tsubst_friend_class PROTO((tree, tree)); +static tree get_bindings_real PROTO((tree, tree, tree, int)); +static int template_decl_level PROTO((tree)); +static tree maybe_get_template_decl_from_type_decl PROTO((tree)); +static int check_cv_quals_for_unify PROTO((int, tree, tree)); +static tree tsubst_template_arg_vector PROTO((tree, tree, int)); +static tree tsubst_template_parms PROTO((tree, tree, int)); +static void regenerate_decl_from_template PROTO((tree, tree)); +static tree most_specialized PROTO((tree, tree, tree)); +static tree most_specialized_class PROTO((tree, tree)); +static tree most_general_template PROTO((tree)); +static void set_mangled_name_for_template_decl PROTO((tree)); +static int template_class_depth_real PROTO((tree, int)); +static tree tsubst_aggr_type PROTO((tree, tree, int, tree, int)); +static tree tsubst_decl PROTO((tree, tree, tree, tree)); +static tree tsubst_arg_types PROTO((tree, tree, int, tree)); +static tree tsubst_function_type PROTO((tree, tree, int, tree)); +static void check_specialization_scope PROTO((void)); +static tree process_partial_specialization PROTO((tree)); +static void set_current_access_from_decl PROTO((tree)); +static void check_default_tmpl_args PROTO((tree, tree, int, int)); +static tree tsubst_call_declarator_parms PROTO((tree, tree, int, tree)); +static tree get_template_base_recursive PROTO((tree, tree, + tree, tree, tree, int)); +static tree get_template_base PROTO((tree, tree, tree, tree)); +static tree try_class_unification PROTO((tree, tree, tree, tree)); +static int coerce_template_template_parms PROTO((tree, tree, int, + tree, tree)); +static tree determine_specialization PROTO((tree, tree, tree *, int)); +static int template_args_equal PROTO((tree, tree)); +static void print_template_context PROTO((int)); +static int has_pvbases_p PROTO((tree, tree)); + +/* We use TREE_VECs to hold template arguments. If there is only one + level of template arguments, then the TREE_VEC contains the + arguments directly. If there is more than one level of template + arguments, then each entry in the TREE_VEC is itself a TREE_VEC, + containing the template arguments for a single level. The first + entry in the outer TREE_VEC is the outermost level of template + parameters; the last is the innermost. + + It is incorrect to ever form a template argument vector containing + only one level of arguments, but which is a TREE_VEC containing as + its only entry the TREE_VEC for that level. */ + +/* Non-zero if the template arguments is actually a vector of vectors, + rather than just a vector. */ +#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \ + (NODE != NULL_TREE \ + && TREE_CODE (NODE) == TREE_VEC \ + && TREE_VEC_LENGTH (NODE) > 0 \ + && TREE_VEC_ELT (NODE, 0) != NULL_TREE \ + && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC) + +/* The depth of a template argument vector. When called directly by + the parser, we use a TREE_LIST rather than a TREE_VEC to represent + template arguments. In fact, we may even see NULL_TREE if there + are no template arguments. In both of those cases, there is only + one level of template arguments. */ +#define TMPL_ARGS_DEPTH(NODE) \ + (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1) + +/* The LEVELth level of the template ARGS. Note that template + parameter levels are indexed from 1, not from 0. */ +#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \ + (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \ + ? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS) + +/* Set the LEVELth level of the template ARGS to VAL. This macro does + not work with single-level argument vectors. */ +#define SET_TMPL_ARGS_LEVEL(ARGS, LEVEL, VAL) \ + (TREE_VEC_ELT ((ARGS), (LEVEL) - 1) = (VAL)) + +/* Accesses the IDXth parameter in the LEVELth level of the ARGS. */ +#define TMPL_ARG(ARGS, LEVEL, IDX) \ + (TREE_VEC_ELT (TMPL_ARGS_LEVEL (ARGS, LEVEL), IDX)) + +/* Set the IDXth element in the LEVELth level of ARGS to VAL. This + macro does not work with single-level argument vectors. */ +#define SET_TMPL_ARG(ARGS, LEVEL, IDX, VAL) \ + (TREE_VEC_ELT (TREE_VEC_ELT ((ARGS), (LEVEL) - 1), (IDX)) = (VAL)) + +/* Given a single level of template arguments in NODE, return the + number of arguments. */ +#define NUM_TMPL_ARGS(NODE) \ + ((NODE) == NULL_TREE ? 0 \ + : (TREE_CODE (NODE) == TREE_VEC \ + ? TREE_VEC_LENGTH (NODE) : list_length (NODE))) + +/* The number of levels of template parameters given by NODE. */ +#define TMPL_PARMS_DEPTH(NODE) \ + (TREE_INT_CST_HIGH (TREE_PURPOSE (NODE))) + +/* Do any processing required when DECL (a member template declaration + using TEMPLATE_PARAMETERS as its innermost parameter list) is + finished. Returns the TEMPLATE_DECL corresponding to DECL, unless + it is a specialization, in which case the DECL itself is returned. */ + +tree +finish_member_template_decl (decl) + tree decl; +{ + if (decl == NULL_TREE || decl == void_type_node) + return NULL_TREE; + else if (decl == error_mark_node) + /* By returning NULL_TREE, the parser will just ignore this + declaration. We have already issued the error. */ + return NULL_TREE; + else if (TREE_CODE (decl) == TREE_LIST) + { + /* Assume that the class is the only declspec. */ + decl = TREE_VALUE (decl); + if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl) + && ! CLASSTYPE_TEMPLATE_SPECIALIZATION (decl)) + { + tree tmpl = CLASSTYPE_TI_TEMPLATE (decl); + check_member_template (tmpl); + return tmpl; + } + return NULL_TREE; + } + else if (DECL_TEMPLATE_INFO (decl)) + { + if (!DECL_TEMPLATE_SPECIALIZATION (decl)) + { + check_member_template (DECL_TI_TEMPLATE (decl)); + return DECL_TI_TEMPLATE (decl); + } + else + return decl; + } + else + cp_error ("invalid member template declaration `%D'", decl); + + return error_mark_node; +} + +/* Returns the template nesting level of the indicated class TYPE. + + For example, in: + template + struct A + { + template + struct B {}; + }; + + A::B has depth two, while A has depth one. + Both A::B and A::B have depth one, if + COUNT_SPECIALIZATIONS is 0 or if they are instantiations, not + specializations. + + This function is guaranteed to return 0 if passed NULL_TREE so + that, for example, `template_class_depth (current_class_type)' is + always safe. */ + +static int +template_class_depth_real (type, count_specializations) + tree type; + int count_specializations; +{ + int depth; + + for (depth = 0; + type && TREE_CODE (type) != NAMESPACE_DECL; + type = (TREE_CODE (type) == FUNCTION_DECL) + ? DECL_REAL_CONTEXT (type) : TYPE_CONTEXT (type)) + { + if (TREE_CODE (type) != FUNCTION_DECL) + { + if (CLASSTYPE_TEMPLATE_INFO (type) + && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)) + && ((count_specializations + && CLASSTYPE_TEMPLATE_SPECIALIZATION (type)) + || uses_template_parms (CLASSTYPE_TI_ARGS (type)))) + ++depth; + } + else + { + if (DECL_TEMPLATE_INFO (type) + && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type)) + && ((count_specializations + && DECL_TEMPLATE_SPECIALIZATION (type)) + || uses_template_parms (DECL_TI_ARGS (type)))) + ++depth; + } + } + + return depth; +} + +/* Returns the template nesting level of the indicated class TYPE. + Like template_class_depth_real, but instantiations do not count in + the depth. */ + +int +template_class_depth (type) + tree type; +{ + return template_class_depth_real (type, /*count_specializations=*/0); +} + +/* Returns 1 if processing DECL as part of do_pending_inlines + needs us to push template parms. */ + +static int +inline_needs_template_parms (decl) + tree decl; +{ + if (! DECL_TEMPLATE_INFO (decl)) + return 0; + + return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl))) + > (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl))); +} + +/* Subroutine of maybe_begin_member_template_processing. + Push the template parms in PARMS, starting from LEVELS steps into the + chain, and ending at the beginning, since template parms are listed + innermost first. */ + +static void +push_inline_template_parms_recursive (parmlist, levels) + tree parmlist; + int levels; +{ + tree parms = TREE_VALUE (parmlist); + int i; + + if (levels > 1) + push_inline_template_parms_recursive (TREE_CHAIN (parmlist), levels - 1); + + ++processing_template_decl; + current_template_parms + = tree_cons (build_int_2 (0, processing_template_decl), + parms, current_template_parms); + TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1; + + pushlevel (0); + for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) + { + tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (parm)) == 'd', 0); + + switch (TREE_CODE (parm)) + { + case TYPE_DECL: + case TEMPLATE_DECL: + pushdecl (parm); + break; + + case PARM_DECL: + { + /* Make a CONST_DECL as is done in process_template_parm. + It is ugly that we recreate this here; the original + version built in process_template_parm is no longer + available. */ + tree decl = build_decl (CONST_DECL, DECL_NAME (parm), + TREE_TYPE (parm)); + SET_DECL_ARTIFICIAL (decl); + DECL_INITIAL (decl) = DECL_INITIAL (parm); + DECL_TEMPLATE_PARM_P (decl) = 1; + pushdecl (decl); + } + break; + + default: + my_friendly_abort (0); + } + } +} + +/* Restore the template parameter context for a member template or + a friend template defined in a class definition. */ + +void +maybe_begin_member_template_processing (decl) + tree decl; +{ + tree parms; + int levels = 0; + + if (inline_needs_template_parms (decl)) + { + parms = DECL_TEMPLATE_PARMS (most_general_template (decl)); + levels = TMPL_PARMS_DEPTH (parms) - processing_template_decl; + + if (DECL_TEMPLATE_SPECIALIZATION (decl)) + { + --levels; + parms = TREE_CHAIN (parms); + } + + push_inline_template_parms_recursive (parms, levels); + } + + /* Remember how many levels of template parameters we pushed so that + we can pop them later. */ + if (!inline_parm_levels) + VARRAY_INT_INIT (inline_parm_levels, 4, "inline_parm_levels"); + if (inline_parm_levels_used == inline_parm_levels->num_elements) + VARRAY_GROW (inline_parm_levels, 2 * inline_parm_levels_used); + VARRAY_INT (inline_parm_levels, inline_parm_levels_used) = levels; + ++inline_parm_levels_used; +} + +/* Undo the effects of begin_member_template_processing. */ + +void +maybe_end_member_template_processing () +{ + int i; + + if (!inline_parm_levels_used) + return; + + --inline_parm_levels_used; + for (i = 0; + i < VARRAY_INT (inline_parm_levels, inline_parm_levels_used); + ++i) + { + --processing_template_decl; + current_template_parms = TREE_CHAIN (current_template_parms); + poplevel (0, 0, 0); + } +} + +/* Returns non-zero iff T is a member template function. We must be + careful as in + + template class C { void f(); } + + Here, f is a template function, and a member, but not a member + template. This function does not concern itself with the origin of + T, only its present state. So if we have + + template class C { template void f(U); } + + then neither C::f nor C::f is considered + to be a member template. But, `template void + C::f(U)' is considered a member template. */ + +int +is_member_template (t) + tree t; +{ + if (!DECL_FUNCTION_TEMPLATE_P (t)) + /* Anything that isn't a function or a template function is + certainly not a member template. */ + return 0; + + /* A local class can't have member templates. */ + if (hack_decl_function_context (t)) + return 0; + + return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t)) + /* If there are more levels of template parameters than + there are template classes surrounding the declaration, + then we have a member template. */ + && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) > + template_class_depth (DECL_CLASS_CONTEXT (t)))); +} + +#if 0 /* UNUSED */ +/* Returns non-zero iff T is a member template class. See + is_member_template for a description of what precisely constitutes + a member template. */ + +int +is_member_template_class (t) + tree t; +{ + if (!DECL_CLASS_TEMPLATE_P (t)) + /* Anything that isn't a class template, is certainly not a member + template. */ + return 0; + + if (!DECL_CLASS_SCOPE_P (t)) + /* Anything whose context isn't a class type is surely not a + member template. */ + return 0; + + /* If there are more levels of template parameters than there are + template classes surrounding the declaration, then we have a + member template. */ + return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) > + template_class_depth (DECL_CONTEXT (t))); +} +#endif + +/* Return a new template argument vector which contains all of ARGS, + but has as its innermost set of arguments the EXTRA_ARGS. The + resulting vector will be built on a temporary obstack, and so must + be explicitly copied to the permanent obstack, if required. */ + +static tree +add_to_template_args (args, extra_args) + tree args; + tree extra_args; +{ + tree new_args; + int extra_depth; + int i; + int j; + + extra_depth = TMPL_ARGS_DEPTH (extra_args); + new_args = make_temp_vec (TMPL_ARGS_DEPTH (args) + extra_depth); + + for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i) + SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i)); + + for (j = 1; j <= extra_depth; ++j, ++i) + SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j)); + + return new_args; +} + +/* Like add_to_template_args, but only the outermost ARGS are added to + the EXTRA_ARGS. In particular, all but TMPL_ARGS_DEPTH + (EXTRA_ARGS) levels are added. This function is used to combine + the template arguments from a partial instantiation with the + template arguments used to attain the full instantiation from the + partial instantiation. */ + +static tree +add_outermost_template_args (args, extra_args) + tree args; + tree extra_args; +{ + tree new_args; + + /* If there are more levels of EXTRA_ARGS than there are ARGS, + something very fishy is going on. */ + my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args), + 0); + + /* If *all* the new arguments will be the EXTRA_ARGS, just return + them. */ + if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args)) + return extra_args; + + /* For the moment, we make ARGS look like it contains fewer levels. */ + TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args); + + new_args = add_to_template_args (args, extra_args); + + /* Now, we restore ARGS to its full dimensions. */ + TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH (extra_args); + + return new_args; +} + +/* We've got a template header coming up; push to a new level for storing + the parms. */ + +void +begin_template_parm_list () +{ + /* We use a non-tag-transparent scope here, which causes pushtag to + put tags in this scope, rather than in the enclosing class or + namespace scope. This is the right thing, since we want + TEMPLATE_DECLS, and not TYPE_DECLS for template classes. For a + global template class, push_template_decl handles putting the + TEMPLATE_DECL into top-level scope. For a nested template class, + e.g.: + + template struct S1 { + template struct S2 {}; + }; + + pushtag contains special code to call pushdecl_with_scope on the + TEMPLATE_DECL for S2. */ + pushlevel (0); + declare_pseudo_global_level (); + ++processing_template_decl; + ++processing_template_parmlist; + note_template_header (0); +} + +/* This routine is called when a specialization is declared. If it is + illegal to declare a specialization here, an error is reported. */ + +static void +check_specialization_scope () +{ + tree scope = current_scope (); + + /* [temp.expl.spec] + + An explicit specialization shall be declared in the namespace of + which the template is a member, or, for member templates, in the + namespace of which the enclosing class or enclosing class + template is a member. An explicit specialization of a member + function, member class or static data member of a class template + shall be declared in the namespace of which the class template + is a member. */ + if (scope && TREE_CODE (scope) != NAMESPACE_DECL) + cp_error ("explicit specialization in non-namespace scope `%D'", + scope); + + /* [temp.expl.spec] + + In an explicit specialization declaration for a member of a class + template or a member template that appears in namespace scope, + the member template and some of its enclosing class templates may + remain unspecialized, except that the declaration shall not + explicitly specialize a class member template if its enclosing + class templates are not explicitly specialized as well. */ + if (current_template_parms) + cp_error ("enclosing class templates are not explicitly specialized"); +} + +/* We've just seen template <>. */ + +void +begin_specialization () +{ + note_template_header (1); + check_specialization_scope (); +} + +/* Called at then end of processing a declaration preceeded by + template<>. */ + +void +end_specialization () +{ + reset_specialization (); +} + +/* Any template <>'s that we have seen thus far are not referring to a + function specialization. */ + +void +reset_specialization () +{ + processing_specialization = 0; + template_header_count = 0; +} + +/* We've just seen a template header. If SPECIALIZATION is non-zero, + it was of the form template <>. */ + +static void +note_template_header (specialization) + int specialization; +{ + processing_specialization = specialization; + template_header_count++; +} + +/* We're beginning an explicit instantiation. */ + +void +begin_explicit_instantiation () +{ + ++processing_explicit_instantiation; +} + + +void +end_explicit_instantiation () +{ + my_friendly_assert(processing_explicit_instantiation > 0, 0); + --processing_explicit_instantiation; +} + +/* The TYPE is being declared. If it is a template type, that means it + is a partial specialization. Do appropriate error-checking. */ + +void +maybe_process_partial_specialization (type) + tree type; +{ + if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type)) + { + if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) + && TYPE_SIZE (type) == NULL_TREE) + { + if (current_namespace + != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type))) + { + cp_pedwarn ("specializing `%#T' in different namespace", type); + cp_pedwarn_at (" from definition of `%#D'", + CLASSTYPE_TI_TEMPLATE (type)); + } + SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type); + if (processing_template_decl) + push_template_decl (TYPE_MAIN_DECL (type)); + } + else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)) + cp_error ("specialization of `%T' after instantiation", type); + } + else if (processing_specialization) + cp_error ("explicit specialization of non-template `%T'", type); +} + +/* Retrieve the specialization (in the sense of [temp.spec] - a + specialization is either an instantiation or an explicit + specialization) of TMPL for the given template ARGS. If there is + no such specialization, return NULL_TREE. The ARGS are a vector of + arguments, or a vector of vectors of arguments, in the case of + templates with more than one level of parameters. */ + +static tree +retrieve_specialization (tmpl, args) + tree tmpl; + tree args; +{ + tree s; + + my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); + + /* There should be as many levels of arguments as there are + levels of parameters. */ + my_friendly_assert (TMPL_ARGS_DEPTH (args) + == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)), + 0); + + for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + s != NULL_TREE; + s = TREE_CHAIN (s)) + if (comp_template_args (TREE_PURPOSE (s), args)) + return TREE_VALUE (s); + + return NULL_TREE; +} + +/* Returns non-zero iff DECL is a specialization of TMPL. */ + +int +is_specialization_of (decl, tmpl) + tree decl; + tree tmpl; +{ + tree t; + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + for (t = decl; + t != NULL_TREE; + t = DECL_TEMPLATE_INFO (t) ? DECL_TI_TEMPLATE (t) : NULL_TREE) + if (t == tmpl) + return 1; + } + else + { + my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 0); + + for (t = TREE_TYPE (decl); + t != NULL_TREE; + t = CLASSTYPE_USE_TEMPLATE (t) + ? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE) + if (same_type_p (TYPE_MAIN_VARIANT (t), + TYPE_MAIN_VARIANT (TREE_TYPE (tmpl)))) + return 1; + } + + return 0; +} + +/* Register the specialization SPEC as a specialization of TMPL with + the indicated ARGS. Returns SPEC, or an equivalent prior + declaration, if available. */ + +static tree +register_specialization (spec, tmpl, args) + tree spec; + tree tmpl; + tree args; +{ + tree s; + + my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); + + if (TREE_CODE (spec) == FUNCTION_DECL + && uses_template_parms (DECL_TI_ARGS (spec))) + /* This is the FUNCTION_DECL for a partial instantiation. Don't + register it; we want the corresponding TEMPLATE_DECL instead. + We use `uses_template_parms (DECL_TI_ARGS (spec))' rather than + the more obvious `uses_template_parms (spec)' to avoid problems + with default function arguments. In particular, given + something like this: + + template void f(T t1, T t = T()) + + the default argument expression is not substituted for in an + instantiation unless and until it is actually needed. */ + return spec; + + /* There should be as many levels of arguments as there are + levels of parameters. */ + my_friendly_assert (TMPL_ARGS_DEPTH (args) + == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)), + 0); + + for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + s != NULL_TREE; + s = TREE_CHAIN (s)) + if (comp_template_args (TREE_PURPOSE (s), args)) + { + tree fn = TREE_VALUE (s); + + if (DECL_TEMPLATE_SPECIALIZATION (spec)) + { + if (DECL_TEMPLATE_INSTANTIATION (fn)) + { + if (TREE_USED (fn) + || DECL_EXPLICIT_INSTANTIATION (fn)) + { + cp_error ("specialization of %D after instantiation", + fn); + return spec; + } + else + { + /* This situation should occur only if the first + specialization is an implicit instantiation, + the second is an explicit specialization, and + the implicit instantiation has not yet been + used. That situation can occur if we have + implicitly instantiated a member function and + then specialized it later. + + We can also wind up here if a friend + declaration that looked like an instantiation + turns out to be a specialization: + + template void foo(T); + class S { friend void foo<>(int) }; + template <> void foo(int); + + We transform the existing DECL in place so that + any pointers to it become pointers to the + updated declaration. + + If there was a definition for the template, but + not for the specialization, we want this to + look as if there is no definition, and vice + versa. */ + DECL_INITIAL (fn) = NULL_TREE; + duplicate_decls (spec, fn); + + return fn; + } + } + else if (DECL_TEMPLATE_SPECIALIZATION (fn)) + { + duplicate_decls (spec, fn); + return fn; + } + } + } + + DECL_TEMPLATE_SPECIALIZATIONS (tmpl) + = perm_tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); + + return spec; +} + +/* Unregister the specialization SPEC as a specialization of TMPL. + Returns nonzero if the SPEC was listed as a specialization of + TMPL. */ + +static int +unregister_specialization (spec, tmpl) + tree spec; + tree tmpl; +{ + tree* s; + + for (s = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + *s != NULL_TREE; + s = &TREE_CHAIN (*s)) + if (TREE_VALUE (*s) == spec) + { + *s = TREE_CHAIN (*s); + return 1; + } + + return 0; +} + +/* Print the list of candidate FNS in an error message. */ + +void +print_candidates (fns) + tree fns; +{ + tree fn; + + const char *str = "candidates are:"; + + for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn)) + { + tree f; + + for (f = TREE_VALUE (fn); f; f = OVL_NEXT (f)) + cp_error_at ("%s %+#D", str, OVL_CURRENT (f)); + str = " "; + } +} + +/* Returns the template (one of the functions given by TEMPLATE_ID) + which can be specialized to match the indicated DECL with the + explicit template args given in TEMPLATE_ID. The DECL may be + NULL_TREE if none is available. In that case, the functions in + TEMPLATE_ID are non-members. + + If NEED_MEMBER_TEMPLATE is non-zero the function is known to be a + specialization of a member template. + + The template args (those explicitly specified and those deduced) + are output in a newly created vector *TARGS_OUT. + + If it is impossible to determine the result, an error message is + issued. The error_mark_node is returned to indicate failure. */ + +static tree +determine_specialization (template_id, decl, targs_out, + need_member_template) + tree template_id; + tree decl; + tree* targs_out; + int need_member_template; +{ + tree fn; + tree fns; + tree targs; + tree explicit_targs; + tree candidates = NULL_TREE; + tree templates = NULL_TREE; + + *targs_out = NULL_TREE; + + if (template_id == error_mark_node) + return error_mark_node; + + fns = TREE_OPERAND (template_id, 0); + explicit_targs = TREE_OPERAND (template_id, 1); + + if (fns == error_mark_node) + return error_mark_node; + + /* Check for baselinks. */ + if (TREE_CODE (fns) == TREE_LIST) + fns = TREE_VALUE (fns); + + for (; fns; fns = OVL_NEXT (fns)) + { + tree tmpl; + + fn = OVL_CURRENT (fns); + + if (TREE_CODE (fn) == TEMPLATE_DECL) + /* DECL might be a specialization of FN. */ + tmpl = fn; + else if (need_member_template) + /* FN is an ordinary member function, and we need a + specialization of a member template. */ + continue; + else if (TREE_CODE (fn) != FUNCTION_DECL) + /* We can get IDENTIFIER_NODEs here in certain erroneous + cases. */ + continue; + else if (!DECL_FUNCTION_MEMBER_P (fn)) + /* This is just an ordinary non-member function. Nothing can + be a specialization of that. */ + continue; + else + { + tree decl_arg_types; + + /* This is an ordinary member function. However, since + we're here, we can assume it's enclosing class is a + template class. For example, + + template struct S { void f(); }; + template <> void S::f() {} + + Here, S::f is a non-template, but S is a + template class. If FN has the same type as DECL, we + might be in business. */ + if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)), + TREE_TYPE (TREE_TYPE (fn)))) + /* The return types differ. */ + continue; + + /* Adjust the type of DECL in case FN is a static member. */ + decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); + if (DECL_STATIC_FUNCTION_P (fn) + && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) + decl_arg_types = TREE_CHAIN (decl_arg_types); + + if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)), + decl_arg_types)) + /* They match! */ + candidates = tree_cons (NULL_TREE, fn, candidates); + + continue; + } + + /* See whether this function might be a specialization of this + template. */ + targs = get_bindings (tmpl, decl, explicit_targs); + + if (!targs) + /* We cannot deduce template arguments that when used to + specialize TMPL will produce DECL. */ + continue; + + /* Save this template, and the arguments deduced. */ + templates = scratch_tree_cons (targs, tmpl, templates); + } + + if (templates && TREE_CHAIN (templates)) + { + /* We have: + + [temp.expl.spec] + + It is possible for a specialization with a given function + signature to be instantiated from more than one function + template. In such cases, explicit specification of the + template arguments must be used to uniquely identify the + function template specialization being specialized. + + Note that here, there's no suggestion that we're supposed to + determine which of the candidate templates is most + specialized. However, we, also have: + + [temp.func.order] + + Partial ordering of overloaded function template + declarations is used in the following contexts to select + the function template to which a function template + specialization refers: + + -- when an explicit specialization refers to a function + template. + + So, we do use the partial ordering rules, at least for now. + This extension can only serve to make illegal programs legal, + so it's safe. And, there is strong anecdotal evidence that + the committee intended the partial ordering rules to apply; + the EDG front-end has that behavior, and John Spicer claims + that the committee simply forgot to delete the wording in + [temp.expl.spec]. */ + tree tmpl = most_specialized (templates, decl, explicit_targs); + if (tmpl && tmpl != error_mark_node) + { + targs = get_bindings (tmpl, decl, explicit_targs); + templates = scratch_tree_cons (targs, tmpl, NULL_TREE); + } + } + + if (templates == NULL_TREE && candidates == NULL_TREE) + { + cp_error_at ("template-id `%D' for `%+D' does not match any template declaration", + template_id, decl); + return error_mark_node; + } + else if ((templates && TREE_CHAIN (templates)) + || (candidates && TREE_CHAIN (candidates)) + || (templates && candidates)) + { + cp_error_at ("ambiguous template specialization `%D' for `%+D'", + template_id, decl); + chainon (candidates, templates); + print_candidates (candidates); + return error_mark_node; + } + + /* We have one, and exactly one, match. */ + if (candidates) + { + /* It was a specialization of an ordinary member function in a + template class. */ + *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates))); + return DECL_TI_TEMPLATE (TREE_VALUE (candidates)); + } + + /* It was a specialization of a template. */ + targs = DECL_TI_ARGS (DECL_RESULT (TREE_VALUE (templates))); + if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs)) + { + *targs_out = copy_node (targs); + SET_TMPL_ARGS_LEVEL (*targs_out, + TMPL_ARGS_DEPTH (*targs_out), + TREE_PURPOSE (templates)); + } + else + *targs_out = TREE_PURPOSE (templates); + return TREE_VALUE (templates); +} + +/* Check to see if the function just declared, as indicated in + DECLARATOR, and in DECL, is a specialization of a function + template. We may also discover that the declaration is an explicit + instantiation at this point. + + Returns DECL, or an equivalent declaration that should be used + instead if all goes well. Issues an error message if something is + amiss. Returns error_mark_node if the error is not easily + recoverable. + + FLAGS is a bitmask consisting of the following flags: + + 2: The function has a definition. + 4: The function is a friend. + + The TEMPLATE_COUNT is the number of references to qualifying + template classes that appeared in the name of the function. For + example, in + + template struct S { void f(); }; + void S::f(); + + the TEMPLATE_COUNT would be 1. However, explicitly specialized + classes are not counted in the TEMPLATE_COUNT, so that in + + template struct S {}; + template <> struct S { void f(); } + template <> void S::f(); + + the TEMPLATE_COUNT would be 0. (Note that this declaration is + illegal; there should be no template <>.) + + If the function is a specialization, it is marked as such via + DECL_TEMPLATE_SPECIALIZATION. Furthermore, its DECL_TEMPLATE_INFO + is set up correctly, and it is added to the list of specializations + for that template. */ + +tree +check_explicit_specialization (declarator, decl, template_count, flags) + tree declarator; + tree decl; + int template_count; + int flags; +{ + int have_def = flags & 2; + int is_friend = flags & 4; + int specialization = 0; + int explicit_instantiation = 0; + int member_specialization = 0; + + tree ctype = DECL_CLASS_CONTEXT (decl); + tree dname = DECL_NAME (decl); + + if (processing_specialization) + { + /* The last template header was of the form template <>. */ + + if (template_header_count > template_count) + { + /* There were more template headers than qualifying template + classes. */ + if (template_header_count - template_count > 1) + /* There shouldn't be that many template parameter lists. + There can be at most one parameter list for every + qualifying class, plus one for the function itself. */ + cp_error ("too many template parameter lists in declaration of `%D'", decl); + + SET_DECL_TEMPLATE_SPECIALIZATION (decl); + if (ctype) + member_specialization = 1; + else + specialization = 1; + } + else if (template_header_count == template_count) + { + /* The counts are equal. So, this might be a + specialization, but it is not a specialization of a + member template. It might be something like + + template struct S { + void f(int i); + }; + template <> + void S::f(int i) {} */ + specialization = 1; + SET_DECL_TEMPLATE_SPECIALIZATION (decl); + } + else + { + /* This cannot be an explicit specialization. There are not + enough headers for all of the qualifying classes. For + example, we might have: + + template <> + void S::T::f(); + + But, we're missing another template <>. */ + cp_error("too few template parameter lists in declaration of `%D'", decl); + return decl; + } + } + else if (processing_explicit_instantiation) + { + if (template_header_count) + cp_error ("template parameter list used in explicit instantiation"); + + if (have_def) + cp_error ("definition provided for explicit instantiation"); + + explicit_instantiation = 1; + } + else if (ctype != NULL_TREE + && !TYPE_BEING_DEFINED (ctype) + && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype) + && !is_friend) + { + /* This case catches outdated code that looks like this: + + template struct S { void f(); }; + void S::f() {} // Missing template <> + + We disable this check when the type is being defined to + avoid complaining about default compiler-generated + constructors, destructors, and assignment operators. + Since the type is an instantiation, not a specialization, + these are the only functions that can be defined before + the class is complete. */ + + /* If they said + template void S::f() {} + that's bogus. */ + if (template_header_count) + { + cp_error ("template parameters specified in specialization"); + return decl; + } + + if (pedantic) + cp_pedwarn + ("explicit specialization not preceded by `template <>'"); + specialization = 1; + SET_DECL_TEMPLATE_SPECIALIZATION (decl); + } + else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) + { + if (is_friend) + /* This could be something like: + + template void f(T); + class S { friend void f<>(int); } */ + specialization = 1; + else + { + /* This case handles bogus declarations like template <> + template void f(); */ + + cp_error ("template-id `%D' in declaration of primary template", + declarator); + return decl; + } + } + + if (specialization || member_specialization) + { + tree t = TYPE_ARG_TYPES (TREE_TYPE (decl)); + for (; t; t = TREE_CHAIN (t)) + if (TREE_PURPOSE (t)) + { + cp_pedwarn + ("default argument specified in explicit specialization"); + break; + } + if (current_lang_name == lang_name_c) + cp_error ("template specialization with C linkage"); + } + + if (specialization || member_specialization || explicit_instantiation) + { + tree tmpl = NULL_TREE; + tree targs = NULL_TREE; + + /* Make sure that the declarator is a TEMPLATE_ID_EXPR. */ + if (TREE_CODE (declarator) != TEMPLATE_ID_EXPR) + { + tree fns; + + my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE, + 0); + if (!ctype) + fns = IDENTIFIER_NAMESPACE_VALUE (dname); + else + fns = dname; + + declarator = + lookup_template_function (fns, NULL_TREE); + } + + if (declarator == error_mark_node) + return error_mark_node; + + if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype)) + { + if (!explicit_instantiation) + /* A specialization in class scope. This is illegal, + but the error will already have been flagged by + check_specialization_scope. */ + return error_mark_node; + else + { + /* It's not legal to write an explicit instantiation in + class scope, e.g.: + + class C { template void f(); } + + This case is caught by the parser. However, on + something like: + + template class C { void f(); }; + + (which is illegal) we can get here. The error will be + issued later. */ + ; + } + + return decl; + } + else if (TREE_CODE (TREE_OPERAND (declarator, 0)) == LOOKUP_EXPR) + { + /* A friend declaration. We can't do much, because we don't + know what this resolves to, yet. */ + my_friendly_assert (is_friend != 0, 0); + my_friendly_assert (!explicit_instantiation, 0); + SET_DECL_IMPLICIT_INSTANTIATION (decl); + return decl; + } + else if (ctype != NULL_TREE + && (TREE_CODE (TREE_OPERAND (declarator, 0)) == + IDENTIFIER_NODE)) + { + /* Find the list of functions in ctype that have the same + name as the declared function. */ + tree name = TREE_OPERAND (declarator, 0); + tree fns = NULL_TREE; + int idx; + + if (name == constructor_name (ctype) + || name == constructor_name_full (ctype)) + { + int is_constructor = DECL_CONSTRUCTOR_P (decl); + + if (is_constructor ? !TYPE_HAS_CONSTRUCTOR (ctype) + : !TYPE_HAS_DESTRUCTOR (ctype)) + { + /* From [temp.expl.spec]: + + If such an explicit specialization for the member + of a class template names an implicitly-declared + special member function (clause _special_), the + program is ill-formed. + + Similar language is found in [temp.explicit]. */ + cp_error ("specialization of implicitly-declared special member function"); + return error_mark_node; + } + + name = is_constructor ? ctor_identifier : dtor_identifier; + } + + if (!IDENTIFIER_TYPENAME_P (name)) + { + idx = lookup_fnfields_1 (ctype, name); + if (idx >= 0) + fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), idx); + } + else + { + tree methods; + + /* For a type-conversion operator, we cannot do a + name-based lookup. We might be looking for `operator + int' which will be a specialization of `operator T'. + So, we find *all* the conversion operators, and then + select from them. */ + fns = NULL_TREE; + + methods = CLASSTYPE_METHOD_VEC (ctype); + if (methods) + for (idx = 2; idx < TREE_VEC_LENGTH (methods); ++idx) + { + tree ovl = TREE_VEC_ELT (methods, idx); + + if (!ovl || !DECL_CONV_FN_P (OVL_CURRENT (ovl))) + /* There are no more conversion functions. */ + break; + + /* Glue all these conversion functions together + with those we already have. */ + for (; ovl; ovl = OVL_NEXT (ovl)) + fns = ovl_cons (OVL_CURRENT (ovl), fns); + } + } + + if (fns == NULL_TREE) + { + cp_error ("no member function `%D' declared in `%T'", + name, ctype); + return error_mark_node; + } + else + TREE_OPERAND (declarator, 0) = fns; + } + + /* Figure out what exactly is being specialized at this point. + Note that for an explicit instantiation, even one for a + member function, we cannot tell apriori whether the + instantiation is for a member template, or just a member + function of a template class. Even if a member template is + being instantiated, the member template arguments may be + elided if they can be deduced from the rest of the + declaration. */ + tmpl = determine_specialization (declarator, decl, + &targs, + member_specialization); + + if (!tmpl || tmpl == error_mark_node) + /* We couldn't figure out what this declaration was + specializing. */ + return error_mark_node; + else + { + tree gen_tmpl = most_general_template (tmpl); + + if (explicit_instantiation) + { + /* We don't set DECL_EXPLICIT_INSTANTIATION here; that + is done by do_decl_instantiation later. */ + + int arg_depth = TMPL_ARGS_DEPTH (targs); + int parm_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)); + + if (arg_depth > parm_depth) + { + /* If TMPL is not the most general template (for + example, if TMPL is a friend template that is + injected into namespace scope), then there will + be too many levels fo TARGS. Remove some of them + here. */ + int i; + tree new_targs; + + new_targs = make_temp_vec (parm_depth); + for (i = arg_depth - parm_depth; i < arg_depth; ++i) + TREE_VEC_ELT (new_targs, i - (arg_depth - parm_depth)) + = TREE_VEC_ELT (targs, i); + targs = new_targs; + } + + decl = instantiate_template (tmpl, targs); + return decl; + } + + /* If we though that the DECL was a member function, but it + turns out to be specializing a static member function, + make DECL a static member function as well. */ + if (DECL_STATIC_FUNCTION_P (tmpl) + && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) + { + revert_static_member_fn (&decl, 0, 0); + last_function_parms = TREE_CHAIN (last_function_parms); + } + + /* Set up the DECL_TEMPLATE_INFO for DECL. */ + DECL_TEMPLATE_INFO (decl) + = perm_tree_cons (tmpl, targs, NULL_TREE); + + /* Mangle the function name appropriately. Note that we do + not mangle specializations of non-template member + functions of template classes, e.g. with + + template struct S { void f(); } + + and given the specialization + + template <> void S::f() {} + + we do not mangle S::f() here. That's because it's + just an ordinary member function and doesn't need special + treatment. We do this here so that the ordinary, + non-template, name-mangling algorith will not be used + later. */ + if ((is_member_template (tmpl) || ctype == NULL_TREE) + && name_mangling_version >= 1) + set_mangled_name_for_template_decl (decl); + + if (is_friend && !have_def) + /* This is not really a declaration of a specialization. + It's just the name of an instantiation. But, it's not + a request for an instantiation, either. */ + SET_DECL_IMPLICIT_INSTANTIATION (decl); + + /* Register this specialization so that we can find it + again. */ + decl = register_specialization (decl, gen_tmpl, targs); + } + } + + return decl; +} + +/* TYPE is being declared. Verify that the use of template headers + and such is reasonable. Issue error messages if not. */ + +void +maybe_check_template_type (type) + tree type; +{ + if (template_header_count) + { + /* We are in the scope of some `template <...>' header. */ + + int context_depth + = template_class_depth_real (TYPE_CONTEXT (type), + /*count_specializations=*/1); + + if (template_header_count <= context_depth) + /* This is OK; the template headers are for the context. We + are actually too lenient here; like + check_explicit_specialization we should consider the number + of template types included in the actual declaration. For + example, + + template struct S { + template template + struct I {}; + }; + + is illegal, but: + + template struct S { + template struct I; + }; + + template template ::I {}; + + is not. */ + ; + else if (template_header_count > context_depth + 1) + /* There are two many template parameter lists. */ + cp_error ("too many template parameter lists in declaration of `%T'", type); + } +} + +/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template + parameters. These are represented in the same format used for + DECL_TEMPLATE_PARMS. */ + +int comp_template_parms (parms1, parms2) + tree parms1; + tree parms2; +{ + tree p1; + tree p2; + + if (parms1 == parms2) + return 1; + + for (p1 = parms1, p2 = parms2; + p1 != NULL_TREE && p2 != NULL_TREE; + p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2)) + { + tree t1 = TREE_VALUE (p1); + tree t2 = TREE_VALUE (p2); + int i; + + my_friendly_assert (TREE_CODE (t1) == TREE_VEC, 0); + my_friendly_assert (TREE_CODE (t2) == TREE_VEC, 0); + + if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2)) + return 0; + + for (i = 0; i < TREE_VEC_LENGTH (t2); ++i) + { + tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i)); + tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i)); + + if (TREE_CODE (parm1) != TREE_CODE (parm2)) + return 0; + + if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM) + continue; + else if (!same_type_p (TREE_TYPE (parm1), TREE_TYPE (parm2))) + return 0; + } + } + + if ((p1 != NULL_TREE) != (p2 != NULL_TREE)) + /* One set of parameters has more parameters lists than the + other. */ + return 0; + + return 1; +} + +/* Complain if DECL shadows a template parameter. + + [temp.local]: A template-parameter shall not be redeclared within its + scope (including nested scopes). */ + +void +check_template_shadow (decl) + tree decl; +{ + tree olddecl; + + /* If we're not in a template, we can't possibly shadow a template + parameter. */ + if (!current_template_parms) + return; + + /* Figure out what we're shadowing. */ + if (TREE_CODE (decl) == OVERLOAD) + decl = OVL_CURRENT (decl); + olddecl = IDENTIFIER_VALUE (DECL_NAME (decl)); + + /* If there's no previous binding for this name, we're not shadowing + anything, let alone a template parameter. */ + if (!olddecl) + return; + + /* If we're not shadowing a template parameter, we're done. Note + that OLDDECL might be an OVERLOAD (or perhaps even an + ERROR_MARK), so we can't just blithely assume it to be a _DECL + node. */ + if (TREE_CODE_CLASS (TREE_CODE (olddecl)) != 'd' + || !DECL_TEMPLATE_PARM_P (olddecl)) + return; + + /* We check for decl != olddecl to avoid bogus errors for using a + name inside a class. We check TPFI to avoid duplicate errors for + inline member templates. */ + if (decl == olddecl + || TEMPLATE_PARMS_FOR_INLINE (current_template_parms)) + return; + + cp_error_at ("declaration of `%#D'", decl); + cp_error_at (" shadows template parm `%#D'", olddecl); +} + +/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL, + ORIG_LEVEL, DECL, and TYPE. */ + +static tree +build_template_parm_index (index, level, orig_level, decl, type) + int index; + int level; + int orig_level; + tree decl; + tree type; +{ + tree t = make_node (TEMPLATE_PARM_INDEX); + TEMPLATE_PARM_IDX (t) = index; + TEMPLATE_PARM_LEVEL (t) = level; + TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level; + TEMPLATE_PARM_DECL (t) = decl; + TREE_TYPE (t) = type; + + return t; +} + +/* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose + TEMPLATE_PARM_LEVEL has been decreased by LEVELS. If such a + TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a + new one is created. */ + +static tree +reduce_template_parm_level (index, type, levels) + tree index; + tree type; + int levels; +{ + if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE + || (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index)) + != TEMPLATE_PARM_LEVEL (index) - levels)) + { + tree decl + = build_decl (TREE_CODE (TEMPLATE_PARM_DECL (index)), + DECL_NAME (TEMPLATE_PARM_DECL (index)), + type); + tree t + = build_template_parm_index (TEMPLATE_PARM_IDX (index), + TEMPLATE_PARM_LEVEL (index) - levels, + TEMPLATE_PARM_ORIG_LEVEL (index), + decl, type); + TEMPLATE_PARM_DESCENDANTS (index) = t; + + /* Template template parameters need this. */ + DECL_TEMPLATE_PARMS (decl) + = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index)); + } + + return TEMPLATE_PARM_DESCENDANTS (index); +} + +/* Process information from new template parameter NEXT and append it to the + LIST being built. */ + +tree +process_template_parm (list, next) + tree list, next; +{ + tree parm; + tree decl = 0; + tree defval; + int is_type, idx; + + parm = next; + my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259); + defval = TREE_PURPOSE (parm); + parm = TREE_VALUE (parm); + is_type = TREE_PURPOSE (parm) == class_type_node; + + if (list) + { + tree p = TREE_VALUE (tree_last (list)); + + if (TREE_CODE (p) == TYPE_DECL) + idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p)); + else if (TREE_CODE (p) == TEMPLATE_DECL) + idx = TEMPLATE_TYPE_IDX (TREE_TYPE (DECL_TEMPLATE_RESULT (p))); + else + idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p)); + ++idx; + } + else + idx = 0; + + if (!is_type) + { + my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260); + /* is a const-param */ + parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm), + PARM, 0, NULL_TREE); + + /* [temp.param] + + The top-level cv-qualifiers on the template-parameter are + ignored when determining its type. */ + TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm)); + + /* A template parameter is not modifiable. */ + TREE_READONLY (parm) = 1; + if (IS_AGGR_TYPE (TREE_TYPE (parm)) + && TREE_CODE (TREE_TYPE (parm)) != TEMPLATE_TYPE_PARM + && TREE_CODE (TREE_TYPE (parm)) != TYPENAME_TYPE) + { + cp_error ("`%#T' is not a valid type for a template constant parameter", + TREE_TYPE (parm)); + if (DECL_NAME (parm) == NULL_TREE) + error (" a template type parameter must begin with `class' or `typename'"); + TREE_TYPE (parm) = void_type_node; + } + else if (pedantic + && (TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE + || TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE)) + cp_pedwarn ("`%T' is not a valid type for a template constant parameter", + TREE_TYPE (parm)); + if (TREE_PERMANENT (parm) == 0) + { + parm = copy_node (parm); + TREE_PERMANENT (parm) = 1; + } + decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm)); + DECL_INITIAL (parm) = DECL_INITIAL (decl) + = build_template_parm_index (idx, processing_template_decl, + processing_template_decl, + decl, TREE_TYPE (parm)); + } + else + { + tree t; + parm = TREE_VALUE (parm); + + if (parm && TREE_CODE (parm) == TEMPLATE_DECL) + { + t = make_lang_type (TEMPLATE_TEMPLATE_PARM); + /* This is for distinguishing between real templates and template + template parameters */ + TREE_TYPE (parm) = t; + TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) = t; + decl = parm; + } + else + { + t = make_lang_type (TEMPLATE_TYPE_PARM); + /* parm is either IDENTIFIER_NODE or NULL_TREE */ + decl = build_decl (TYPE_DECL, parm, t); + } + + TYPE_NAME (t) = decl; + TYPE_STUB_DECL (t) = decl; + parm = decl; + TEMPLATE_TYPE_PARM_INDEX (t) + = build_template_parm_index (idx, processing_template_decl, + processing_template_decl, + decl, TREE_TYPE (parm)); + } + SET_DECL_ARTIFICIAL (decl); + DECL_TEMPLATE_PARM_P (decl) = 1; + pushdecl (decl); + parm = build_tree_list (defval, parm); + return chainon (list, parm); +} + +/* The end of a template parameter list has been reached. Process the + tree list into a parameter vector, converting each parameter into a more + useful form. Type parameters are saved as IDENTIFIER_NODEs, and others + as PARM_DECLs. */ + +tree +end_template_parm_list (parms) + tree parms; +{ + int nparms; + tree parm; + tree saved_parmlist = make_tree_vec (list_length (parms)); + + current_template_parms + = tree_cons (build_int_2 (0, processing_template_decl), + saved_parmlist, current_template_parms); + + for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++) + TREE_VEC_ELT (saved_parmlist, nparms) = parm; + + --processing_template_parmlist; + + return saved_parmlist; +} + +/* end_template_decl is called after a template declaration is seen. */ + +void +end_template_decl () +{ + reset_specialization (); + + if (! processing_template_decl) + return; + + /* This matches the pushlevel in begin_template_parm_list. */ + poplevel (0, 0, 0); + + --processing_template_decl; + current_template_parms = TREE_CHAIN (current_template_parms); + (void) get_pending_sizes (); /* Why? */ +} + +/* Given a template argument vector containing the template PARMS. + The innermost PARMS are given first. */ + +tree +current_template_args () +{ + tree header; + tree args = NULL_TREE; + int length = TMPL_PARMS_DEPTH (current_template_parms); + int l = length; + + /* If there is only one level of template parameters, we do not + create a TREE_VEC of TREE_VECs. Instead, we return a single + TREE_VEC containing the arguments. */ + if (length > 1) + args = make_tree_vec (length); + + for (header = current_template_parms; header; header = TREE_CHAIN (header)) + { + tree a = copy_node (TREE_VALUE (header)); + int i; + + TREE_TYPE (a) = NULL_TREE; + for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i) + { + tree t = TREE_VEC_ELT (a, i); + + /* T will be a list if we are called from within a + begin/end_template_parm_list pair, but a vector directly + if within a begin/end_member_template_processing pair. */ + if (TREE_CODE (t) == TREE_LIST) + { + t = TREE_VALUE (t); + + if (TREE_CODE (t) == TYPE_DECL + || TREE_CODE (t) == TEMPLATE_DECL) + t = TREE_TYPE (t); + else + t = DECL_INITIAL (t); + TREE_VEC_ELT (a, i) = t; + } + } + + if (length > 1) + TREE_VEC_ELT (args, --l) = a; + else + args = a; + } + + return args; +} + +/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated + template PARMS. Used by push_template_decl below. */ + +static tree +build_template_decl (decl, parms) + tree decl; + tree parms; +{ + tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE); + DECL_TEMPLATE_PARMS (tmpl) = parms; + DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl); + if (DECL_LANG_SPECIFIC (decl)) + { + DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl); + DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl); + DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl); + } + + return tmpl; +} + +struct template_parm_data +{ + /* The level of the template parameters we are currently + processing. */ + int level; + + /* The index of the specialization argument we are currently + processing. */ + int current_arg; + + /* An array whose size is the number of template parameters. The + elements are non-zero if the parameter has been used in any one + of the arguments processed so far. */ + int* parms; + + /* An array whose size is the number of template arguments. The + elements are non-zero if the argument makes use of template + parameters of this level. */ + int* arg_uses_template_parms; +}; + +/* Subroutine of push_template_decl used to see if each template + parameter in a partial specialization is used in the explicit + argument list. If T is of the LEVEL given in DATA (which is + treated as a template_parm_data*), then DATA->PARMS is marked + appropriately. */ + +static int +mark_template_parm (t, data) + tree t; + void* data; +{ + int level; + int idx; + struct template_parm_data* tpd = (struct template_parm_data*) data; + + if (TREE_CODE (t) == TEMPLATE_PARM_INDEX) + { + level = TEMPLATE_PARM_LEVEL (t); + idx = TEMPLATE_PARM_IDX (t); + } + else + { + level = TEMPLATE_TYPE_LEVEL (t); + idx = TEMPLATE_TYPE_IDX (t); + } + + if (level == tpd->level) + { + tpd->parms[idx] = 1; + tpd->arg_uses_template_parms[tpd->current_arg] = 1; + } + + /* Return zero so that for_each_template_parm will continue the + traversal of the tree; we want to mark *every* template parm. */ + return 0; +} + +/* Process the partial specialization DECL. */ + +static tree +process_partial_specialization (decl) + tree decl; +{ + tree type = TREE_TYPE (decl); + tree maintmpl = CLASSTYPE_TI_TEMPLATE (type); + tree specargs = CLASSTYPE_TI_ARGS (type); + tree inner_args = innermost_args (specargs); + tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); + tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl); + int nargs = TREE_VEC_LENGTH (inner_args); + int ntparms = TREE_VEC_LENGTH (inner_parms); + int i; + int did_error_intro = 0; + struct template_parm_data tpd; + struct template_parm_data tpd2; + + /* We check that each of the template parameters given in the + partial specialization is used in the argument list to the + specialization. For example: + + template struct S; + template struct S; + + The second declaration is OK because `T*' uses the template + parameter T, whereas + + template struct S; + + is no good. Even trickier is: + + template + struct S1 + { + template + struct S2; + template + struct S2; + }; + + The S2 declaration is actually illegal; it is a + full-specialization. Of course, + + template + struct S2; + + or some such would have been OK. */ + tpd.level = TMPL_PARMS_DEPTH (current_template_parms); + tpd.parms = alloca (sizeof (int) * ntparms); + bzero ((PTR) tpd.parms, sizeof (int) * ntparms); + + tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs); + bzero ((PTR) tpd.arg_uses_template_parms, sizeof (int) * nargs); + for (i = 0; i < nargs; ++i) + { + tpd.current_arg = i; + for_each_template_parm (TREE_VEC_ELT (inner_args, i), + &mark_template_parm, + &tpd); + } + for (i = 0; i < ntparms; ++i) + if (tpd.parms[i] == 0) + { + /* One of the template parms was not used in the + specialization. */ + if (!did_error_intro) + { + cp_error ("template parameters not used in partial specialization:"); + did_error_intro = 1; + } + + cp_error (" `%D'", + TREE_VALUE (TREE_VEC_ELT (inner_parms, i))); + } + + /* [temp.class.spec] + + The argument list of the specialization shall not be identical to + the implicit argument list of the primary template. */ + if (comp_template_args (inner_args, + innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE + (maintmpl))))) + cp_error ("partial specialization `%T' does not specialize any template arguments", type); + + /* [temp.class.spec] + + A partially specialized non-type argument expression shall not + involve template parameters of the partial specialization except + when the argument expression is a simple identifier. + + The type of a template parameter corresponding to a specialized + non-type argument shall not be dependent on a parameter of the + specialization. */ + my_friendly_assert (nargs == DECL_NTPARMS (maintmpl), 0); + tpd2.parms = 0; + for (i = 0; i < nargs; ++i) + { + tree arg = TREE_VEC_ELT (inner_args, i); + if (/* These first two lines are the `non-type' bit. */ + TREE_CODE_CLASS (TREE_CODE (arg)) != 't' + && TREE_CODE (arg) != TEMPLATE_DECL + /* This next line is the `argument expression is not just a + simple identifier' condition and also the `specialized + non-type argument' bit. */ + && TREE_CODE (arg) != TEMPLATE_PARM_INDEX) + { + if (tpd.arg_uses_template_parms[i]) + cp_error ("template argument `%E' involves template parameter(s)", arg); + else + { + /* Look at the corresponding template parameter, + marking which template parameters its type depends + upon. */ + tree type = + TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (main_inner_parms, + i))); + + if (!tpd2.parms) + { + /* We haven't yet initialized TPD2. Do so now. */ + tpd2.arg_uses_template_parms + = (int*) alloca (sizeof (int) * nargs); + /* The number of parameters here is the number in the + main template, which, as checked in the assertion + above, is NARGS. */ + tpd2.parms = (int*) alloca (sizeof (int) * nargs); + tpd2.level = + TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl)); + } + + /* Mark the template parameters. But this time, we're + looking for the template parameters of the main + template, not in the specialization. */ + tpd2.current_arg = i; + tpd2.arg_uses_template_parms[i] = 0; + bzero ((PTR) tpd2.parms, sizeof (int) * nargs); + for_each_template_parm (type, + &mark_template_parm, + &tpd2); + + if (tpd2.arg_uses_template_parms [i]) + { + /* The type depended on some template parameters. + If they are fully specialized in the + specialization, that's OK. */ + int j; + for (j = 0; j < nargs; ++j) + if (tpd2.parms[j] != 0 + && tpd.arg_uses_template_parms [j]) + { + cp_error ("type `%T' of template argument `%E' depends on template parameter(s)", + type, + arg); + break; + } + } + } + } + } + + if (retrieve_specialization (maintmpl, specargs)) + /* We've already got this specialization. */ + return decl; + + DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type) + = perm_tree_cons (inner_args, inner_parms, + DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)); + TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type; + return decl; +} + +/* Check that a template declaration's use of default arguments is not + invalid. Here, PARMS are the template parameters. IS_PRIMARY is + non-zero if DECL is the thing declared by a primary template. + IS_PARTIAL is non-zero if DECL is a partial specialization. */ + +static void +check_default_tmpl_args (decl, parms, is_primary, is_partial) + tree decl; + tree parms; + int is_primary; + int is_partial; +{ + const char *msg; + int last_level_to_check; + + /* [temp.param] + + A default template-argument shall not be specified in a + function template declaration or a function template definition, nor + in the template-parameter-list of the definition of a member of a + class template. */ + + if (current_class_type + && !TYPE_BEING_DEFINED (current_class_type) + && DECL_LANG_SPECIFIC (decl) + /* If this is either a friend defined in the scope of the class + or a member function. */ + && DECL_CLASS_CONTEXT (decl) == current_class_type + /* And, if it was a member function, it really was defined in + the scope of the class. */ + && (!DECL_FUNCTION_MEMBER_P (decl) || DECL_DEFINED_IN_CLASS_P (decl))) + /* We already checked these parameters when the template was + declared, so there's no need to do it again now. This function + was defined in class scope, but we're processing it's body now + that the class is complete. */ + return; + + if (TREE_CODE (decl) != TYPE_DECL || is_partial || !is_primary) + /* For an ordinary class template, default template arguments are + allowed at the innermost level, e.g.: + template + struct S {}; + but, in a partial specialization, they're not allowed even + there, as we have in [temp.class.spec]: + + The template parameter list of a specialization shall not + contain default template argument values. + + So, for a partial specialization, or for a function template, + we look at all of them. */ + ; + else + /* But, for a primary class template that is not a partial + specialization we look at all template parameters except the + innermost ones. */ + parms = TREE_CHAIN (parms); + + /* Figure out what error message to issue. */ + if (TREE_CODE (decl) == FUNCTION_DECL) + msg = "default argument for template parameter in function template `%D'"; + else if (is_partial) + msg = "default argument in partial specialization `%D'"; + else + msg = "default argument for template parameter for class enclosing `%D'"; + + if (current_class_type && TYPE_BEING_DEFINED (current_class_type)) + /* If we're inside a class definition, there's no need to + examine the parameters to the class itself. On the one + hand, they will be checked when the class is defined, and, + on the other, default arguments are legal in things like: + template + struct S { template void f(U); }; + Here the default argument for `S' has no bearing on the + declaration of `f'. */ + last_level_to_check = template_class_depth (current_class_type) + 1; + else + /* Check everything. */ + last_level_to_check = 0; + + for (; parms && TMPL_PARMS_DEPTH (parms) >= last_level_to_check; + parms = TREE_CHAIN (parms)) + { + tree inner_parms = TREE_VALUE (parms); + int i, ntparms; + + ntparms = TREE_VEC_LENGTH (inner_parms); + for (i = 0; i < ntparms; ++i) + if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i))) + { + if (msg) + { + cp_error (msg, decl); + msg = 0; + } + + /* Clear out the default argument so that we are not + confused later. */ + TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE; + } + + /* At this point, if we're still interested in issuing messages, + they must apply to classes surrounding the object declared. */ + if (msg) + msg = "default argument for template parameter for class enclosing `%D'"; + } +} + +/* Creates a TEMPLATE_DECL for the indicated DECL using the template + parameters given by current_template_args, or reuses a + previously existing one, if appropriate. Returns the DECL, or an + equivalent one, if it is replaced via a call to duplicate_decls. + + If IS_FRIEND is non-zero, DECL is a friend declaration. */ + +tree +push_template_decl_real (decl, is_friend) + tree decl; + int is_friend; +{ + tree tmpl; + tree args; + tree info; + tree ctx; + int primary; + int is_partial; + + /* See if this is a partial specialization. */ + is_partial = (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl) + && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE + && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl))); + + is_friend |= (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl)); + + if (is_friend) + /* For a friend, we want the context of the friend function, not + the type of which it is a friend. */ + ctx = DECL_CONTEXT (decl); + else if (DECL_REAL_CONTEXT (decl) + && TREE_CODE (DECL_REAL_CONTEXT (decl)) != NAMESPACE_DECL) + /* In the case of a virtual function, we want the class in which + it is defined. */ + ctx = DECL_REAL_CONTEXT (decl); + else + /* Otherwise, if we're currently definining some class, the DECL + is assumed to be a member of the class. */ + ctx = current_class_type; + + if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL) + ctx = NULL_TREE; + + if (!DECL_CONTEXT (decl)) + DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); + + /* For determining whether this is a primary template or not, we're really + interested in the lexical context, not the true context. */ + if (is_friend) + info = current_class_type; + else + info = ctx; + + /* See if this is a primary template. */ + if (info && TREE_CODE (info) == FUNCTION_DECL) + primary = 0; + /* Note that template_class_depth returns 0 if given NULL_TREE, so + this next line works even when we are at global scope. */ + else if (processing_template_decl > template_class_depth (info)) + primary = 1; + else + primary = 0; + + if (primary) + { + if (current_lang_name == lang_name_c) + cp_error ("template with C linkage"); + if (TREE_CODE (decl) == TYPE_DECL && ANON_AGGRNAME_P (DECL_NAME (decl))) + cp_error ("template class without a name"); + if (TREE_CODE (decl) == TYPE_DECL + && TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE) + cp_error ("template declaration of `%#T'", TREE_TYPE (decl)); + } + + /* Check to see that the rules regarding the use of default + arguments are not being violated. */ + check_default_tmpl_args (decl, current_template_parms, + primary, is_partial); + + if (is_partial) + return process_partial_specialization (decl); + + args = current_template_args (); + + if (!ctx + || TREE_CODE (ctx) == FUNCTION_DECL + || TYPE_BEING_DEFINED (ctx) + || (is_friend && !DECL_TEMPLATE_INFO (decl))) + { + if (DECL_LANG_SPECIFIC (decl) + && DECL_TEMPLATE_INFO (decl) + && DECL_TI_TEMPLATE (decl)) + tmpl = DECL_TI_TEMPLATE (decl); + else + { + tmpl = build_template_decl (decl, current_template_parms); + + if (DECL_LANG_SPECIFIC (decl) + && DECL_TEMPLATE_SPECIALIZATION (decl)) + { + /* A specialization of a member template of a template + class. */ + SET_DECL_TEMPLATE_SPECIALIZATION (tmpl); + DECL_TEMPLATE_INFO (tmpl) = DECL_TEMPLATE_INFO (decl); + DECL_TEMPLATE_INFO (decl) = NULL_TREE; + } + } + } + else + { + tree a, t, current, parms; + int i; + + if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx)) + cp_error ("must specialize `%#T' before defining member `%#D'", + ctx, decl); + if (TREE_CODE (decl) == TYPE_DECL) + { + if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl))) + || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE) + && TYPE_TEMPLATE_INFO (TREE_TYPE (decl)) + && TYPE_TI_TEMPLATE (TREE_TYPE (decl))) + tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl)); + else + { + cp_error ("`%D' does not declare a template type", decl); + return decl; + } + } + else if (! DECL_TEMPLATE_INFO (decl)) + { + cp_error ("template definition of non-template `%#D'", decl); + return decl; + } + else + tmpl = DECL_TI_TEMPLATE (decl); + + if (is_member_template (tmpl) + && DECL_FUNCTION_TEMPLATE_P (tmpl) + && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl) + && DECL_TEMPLATE_SPECIALIZATION (decl)) + { + tree new_tmpl; + + /* The declaration is a specialization of a member + template, declared outside the class. Therefore, the + innermost template arguments will be NULL, so we + replace them with the arguments determined by the + earlier call to check_explicit_specialization. */ + args = DECL_TI_ARGS (decl); + + new_tmpl + = build_template_decl (decl, current_template_parms); + DECL_TEMPLATE_RESULT (new_tmpl) = decl; + TREE_TYPE (new_tmpl) = TREE_TYPE (decl); + DECL_TI_TEMPLATE (decl) = new_tmpl; + SET_DECL_TEMPLATE_SPECIALIZATION (new_tmpl); + DECL_TEMPLATE_INFO (new_tmpl) = + perm_tree_cons (tmpl, args, NULL_TREE); + + register_specialization (new_tmpl, tmpl, args); + return decl; + } + + /* Make sure the template headers we got make sense. */ + + parms = DECL_TEMPLATE_PARMS (tmpl); + i = TMPL_PARMS_DEPTH (parms); + if (TMPL_ARGS_DEPTH (args) != i) + { + cp_error ("expected %d levels of template parms for `%#D', got %d", + i, decl, TMPL_ARGS_DEPTH (args)); + } + else + for (current = decl; i > 0; --i, parms = TREE_CHAIN (parms)) + { + a = TMPL_ARGS_LEVEL (args, i); + t = INNERMOST_TEMPLATE_PARMS (parms); + + if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a)) + { + if (current == decl) + cp_error ("got %d template parameters for `%#D'", + TREE_VEC_LENGTH (a), decl); + else + cp_error ("got %d template parameters for `%#T'", + TREE_VEC_LENGTH (a), current); + cp_error (" but %d required", TREE_VEC_LENGTH (t)); + } + + /* Perhaps we should also check that the parms are used in the + appropriate qualifying scopes in the declarator? */ + + if (current == decl) + current = ctx; + else + current = TYPE_CONTEXT (current); + } + } + + DECL_TEMPLATE_RESULT (tmpl) = decl; + TREE_TYPE (tmpl) = TREE_TYPE (decl); + + /* Push template declarations for global functions and types. Note + that we do not try to push a global template friend declared in a + template class; such a thing may well depend on the template + parameters of the class. */ + if (! ctx + && !(is_friend && template_class_depth (current_class_type) > 0)) + tmpl = pushdecl_namespace_level (tmpl); + + if (primary) + DECL_PRIMARY_TEMPLATE (tmpl) = tmpl; + + info = perm_tree_cons (tmpl, args, NULL_TREE); + + if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)) + { + SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info); + if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL) + && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE) + DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl)); + } + else if (! DECL_LANG_SPECIFIC (decl)) + cp_error ("template declaration of `%#D'", decl); + else + DECL_TEMPLATE_INFO (decl) = info; + + return DECL_TEMPLATE_RESULT (tmpl); +} + +tree +push_template_decl (decl) + tree decl; +{ + return push_template_decl_real (decl, 0); +} + +/* Called when a class template TYPE is redeclared with the indicated + template PARMS, e.g.: + + template struct S; + template struct S {}; */ + +void +redeclare_class_template (type, parms) + tree type; + tree parms; +{ + tree tmpl; + tree tmpl_parms; + int i; + + if (!TYPE_TEMPLATE_INFO (type)) + { + cp_error ("`%T' is not a template type", type); + return; + } + + tmpl = TYPE_TI_TEMPLATE (type); + if (!PRIMARY_TEMPLATE_P (tmpl)) + /* The type is nested in some template class. Nothing to worry + about here; there are no new template parameters for the nested + type. */ + return; + + parms = INNERMOST_TEMPLATE_PARMS (parms); + tmpl_parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); + + if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms)) + { + cp_error_at ("previous declaration `%D'", tmpl); + cp_error ("used %d template parameter%s instead of %d", + TREE_VEC_LENGTH (tmpl_parms), + TREE_VEC_LENGTH (tmpl_parms) == 1 ? "" : "s", + TREE_VEC_LENGTH (parms)); + return; + } + + for (i = 0; i < TREE_VEC_LENGTH (tmpl_parms); ++i) + { + tree tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i)); + tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); + tree tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i)); + tree parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i)); + + if (TREE_CODE (tmpl_parm) != TREE_CODE (parm)) + { + cp_error_at ("template parameter `%#D'", tmpl_parm); + cp_error ("redeclared here as `%#D'", parm); + return; + } + + if (tmpl_default != NULL_TREE && parm_default != NULL_TREE) + { + /* We have in [temp.param]: + + A template-parameter may not be given default arguments + by two different declarations in the same scope. */ + cp_error ("redefinition of default argument for `%#D'", parm); + cp_error_at (" original definition appeared here", tmpl_parm); + return; + } + + if (parm_default != NULL_TREE) + /* Update the previous template parameters (which are the ones + that will really count) with the new default value. */ + TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i)) = parm_default; + } +} + +/* Attempt to convert the non-type template parameter EXPR to the + indicated TYPE. If the conversion is successful, return the + converted value. If the conversion is unsuccesful, return + NULL_TREE if we issued an error message, or error_mark_node if we + did not. We issue error messages for out-and-out bad template + parameters, but not simply because the conversion failed, since we + might be just trying to do argument deduction. By the time this + function is called, neither TYPE nor EXPR may make use of template + parameters. */ + +static tree +convert_nontype_argument (type, expr) + tree type; + tree expr; +{ + tree expr_type = TREE_TYPE (expr); + + /* A template-argument for a non-type, non-template + template-parameter shall be one of: + + --an integral constant-expression of integral or enumeration + type; or + + --the name of a non-type template-parameter; or + + --the name of an object or function with external linkage, + including function templates and function template-ids but + excluding non-static class members, expressed as id-expression; + or + + --the address of an object or function with external linkage, + including function templates and function template-ids but + excluding non-static class members, expressed as & id-expression + where the & is optional if the name refers to a function or + array; or + + --a pointer to member expressed as described in _expr.unary.op_. */ + + /* An integral constant-expression can include const variables + or enumerators. */ + if (INTEGRAL_TYPE_P (expr_type) && TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); + + if (is_overloaded_fn (expr)) + /* OK for now. We'll check that it has external linkage later. + Check this first since if expr_type is the unknown_type_node + we would otherwise complain below. */ + ; + else if (TYPE_PTRMEM_P (expr_type) + || TYPE_PTRMEMFUNC_P (expr_type)) + { + if (TREE_CODE (expr) != PTRMEM_CST) + goto bad_argument; + } + else if (TYPE_PTR_P (expr_type) + || TYPE_PTRMEM_P (expr_type) + || TREE_CODE (expr_type) == ARRAY_TYPE + || TREE_CODE (type) == REFERENCE_TYPE + /* If expr is the address of an overloaded function, we + will get the unknown_type_node at this point. */ + || expr_type == unknown_type_node) + { + tree referent; + tree e = expr; + STRIP_NOPS (e); + + if (TREE_CODE (type) == REFERENCE_TYPE + || TREE_CODE (expr_type) == ARRAY_TYPE) + referent = e; + else + { + if (TREE_CODE (e) != ADDR_EXPR) + { + bad_argument: + cp_error ("`%E' is not a valid template argument", expr); + if (TYPE_PTR_P (expr_type)) + { + if (TREE_CODE (TREE_TYPE (expr_type)) == FUNCTION_TYPE) + cp_error ("it must be the address of a function with external linkage"); + else + cp_error ("it must be the address of an object with external linkage"); + } + else if (TYPE_PTRMEM_P (expr_type) + || TYPE_PTRMEMFUNC_P (expr_type)) + cp_error ("it must be a pointer-to-member of the form `&X::Y'"); + + return NULL_TREE; + } + + referent = TREE_OPERAND (e, 0); + STRIP_NOPS (referent); + } + + if (TREE_CODE (referent) == STRING_CST) + { + cp_error ("string literal %E is not a valid template argument", + referent); + error ("because it is the address of an object with static linkage"); + return NULL_TREE; + } + + if (is_overloaded_fn (referent)) + /* We'll check that it has external linkage later. */ + ; + else if (TREE_CODE (referent) != VAR_DECL) + goto bad_argument; + else if (!TREE_PUBLIC (referent)) + { + cp_error ("address of non-extern `%E' cannot be used as template argument", referent); + return error_mark_node; + } + } + else if (INTEGRAL_TYPE_P (expr_type) + || TYPE_PTRMEM_P (expr_type) + || TYPE_PTRMEMFUNC_P (expr_type) + /* The next two are g++ extensions. */ + || TREE_CODE (expr_type) == REAL_TYPE + || TREE_CODE (expr_type) == COMPLEX_TYPE) + { + if (! TREE_CONSTANT (expr)) + { + non_constant: + cp_error ("non-constant `%E' cannot be used as template argument", + expr); + return NULL_TREE; + } + } + else + { + cp_error ("object `%E' cannot be used as template argument", expr); + return NULL_TREE; + } + + switch (TREE_CODE (type)) + { + case INTEGER_TYPE: + case BOOLEAN_TYPE: + case ENUMERAL_TYPE: + /* For a non-type template-parameter of integral or enumeration + type, integral promotions (_conv.prom_) and integral + conversions (_conv.integral_) are applied. */ + if (!INTEGRAL_TYPE_P (expr_type)) + return error_mark_node; + + /* It's safe to call digest_init in this case; we know we're + just converting one integral constant expression to another. */ + expr = digest_init (type, expr, (tree*) 0); + + if (TREE_CODE (expr) != INTEGER_CST) + /* Curiously, some TREE_CONSTANT integral expressions do not + simplify to integer constants. For example, `3 % 0', + remains a TRUNC_MOD_EXPR. */ + goto non_constant; + + return expr; + + case REAL_TYPE: + case COMPLEX_TYPE: + /* These are g++ extensions. */ + if (TREE_CODE (expr_type) != TREE_CODE (type)) + return error_mark_node; + + expr = digest_init (type, expr, (tree*) 0); + + if (TREE_CODE (expr) != REAL_CST) + goto non_constant; + + return expr; + + case POINTER_TYPE: + { + tree type_pointed_to = TREE_TYPE (type); + + if (TYPE_PTRMEM_P (type)) + { + tree e; + + /* For a non-type template-parameter of type pointer to data + member, qualification conversions (_conv.qual_) are + applied. */ + e = perform_qualification_conversions (type, expr); + if (TREE_CODE (e) == NOP_EXPR) + /* The call to perform_qualification_conversions will + insert a NOP_EXPR over EXPR to do express conversion, + if necessary. But, that will confuse us if we use + this (converted) template parameter to instantiate + another template; then the thing will not look like a + valid template argument. So, just make a new + constant, of the appropriate type. */ + e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr)); + return e; + } + else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE) + { + /* For a non-type template-parameter of type pointer to + function, only the function-to-pointer conversion + (_conv.func_) is applied. If the template-argument + represents a set of overloaded functions (or a pointer to + such), the matching function is selected from the set + (_over.over_). */ + tree fns; + tree fn; + + if (TREE_CODE (expr) == ADDR_EXPR) + fns = TREE_OPERAND (expr, 0); + else + fns = expr; + + fn = instantiate_type (type_pointed_to, fns, 0); + + if (fn == error_mark_node) + return error_mark_node; + + if (!TREE_PUBLIC (fn)) + { + if (really_overloaded_fn (fns)) + return error_mark_node; + else + goto bad_argument; + } + + expr = build_unary_op (ADDR_EXPR, fn, 0); + + my_friendly_assert (same_type_p (type, TREE_TYPE (expr)), + 0); + return expr; + } + else + { + /* For a non-type template-parameter of type pointer to + object, qualification conversions (_conv.qual_) and the + array-to-pointer conversion (_conv.array_) are applied. + [Note: In particular, neither the null pointer conversion + (_conv.ptr_) nor the derived-to-base conversion + (_conv.ptr_) are applied. Although 0 is a valid + template-argument for a non-type template-parameter of + integral type, it is not a valid template-argument for a + non-type template-parameter of pointer type.] + + The call to decay_conversion performs the + array-to-pointer conversion, if appropriate. */ + expr = decay_conversion (expr); + + if (expr == error_mark_node) + return error_mark_node; + else + return perform_qualification_conversions (type, expr); + } + } + break; + + case REFERENCE_TYPE: + { + tree type_referred_to = TREE_TYPE (type); + + if (TREE_CODE (type_referred_to) == FUNCTION_TYPE) + { + /* For a non-type template-parameter of type reference to + function, no conversions apply. If the + template-argument represents a set of overloaded + functions, the matching function is selected from the + set (_over.over_). */ + tree fns = expr; + tree fn; + + fn = instantiate_type (type_referred_to, fns, 0); + + if (fn == error_mark_node) + return error_mark_node; + + if (!TREE_PUBLIC (fn)) + { + if (really_overloaded_fn (fns)) + /* Don't issue an error here; we might get a different + function if the overloading had worked out + differently. */ + return error_mark_node; + else + goto bad_argument; + } + + my_friendly_assert (same_type_p (type_referred_to, + TREE_TYPE (fn)), + 0); + + return fn; + } + else + { + /* For a non-type template-parameter of type reference to + object, no conversions apply. The type referred to by the + reference may be more cv-qualified than the (otherwise + identical) type of the template-argument. The + template-parameter is bound directly to the + template-argument, which must be an lvalue. */ + if ((TYPE_MAIN_VARIANT (expr_type) + != TYPE_MAIN_VARIANT (type_referred_to)) + || !at_least_as_qualified_p (type_referred_to, + expr_type) + || !real_lvalue_p (expr)) + return error_mark_node; + else + return expr; + } + } + break; + + case RECORD_TYPE: + { + if (!TYPE_PTRMEMFUNC_P (type)) + /* This handles templates like + template void f(); + when T is substituted with any class. The second template + parameter becomes invalid and the template candidate is + rejected. */ + return error_mark_node; + + /* For a non-type template-parameter of type pointer to member + function, no conversions apply. If the template-argument + represents a set of overloaded member functions, the + matching member function is selected from the set + (_over.over_). */ + + if (!TYPE_PTRMEMFUNC_P (expr_type) && + expr_type != unknown_type_node) + return error_mark_node; + + if (TREE_CODE (expr) == PTRMEM_CST) + { + /* A ptr-to-member constant. */ + if (!same_type_p (type, expr_type)) + return error_mark_node; + else + return expr; + } + + if (TREE_CODE (expr) != ADDR_EXPR) + return error_mark_node; + + expr = instantiate_type (type, expr, 0); + + if (expr == error_mark_node) + return error_mark_node; + + my_friendly_assert (same_type_p (type, TREE_TYPE (expr)), + 0); + return expr; + } + break; + + default: + /* All non-type parameters must have one of these types. */ + my_friendly_abort (0); + break; + } + + return error_mark_node; +} + +/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for + template template parameters. Both PARM_PARMS and ARG_PARMS are + vectors of TREE_LIST nodes containing TYPE_DECL, TEMPLATE_DECL + or PARM_DECL. + + ARG_PARMS may contain more parameters than PARM_PARMS. If this is + the case, then extra parameters must have default arguments. + + Consider the example: + template class vector; + template