Initial revision

From-SVN: r6613
This commit is contained in:
Mike Stump 1994-02-24 01:02:37 +00:00
parent f8a9e02bc1
commit 8d08fdba59
32 changed files with 67714 additions and 0 deletions

318
gcc/cp/Makefile.in Normal file
View File

@ -0,0 +1,318 @@
# Makefile for GNU C++ compiler.
# Copyright (C) 1987, 88, 90, 91, 92, 93, 1994 Free Software Foundation, Inc.
#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, 675 Mass Ave, Cambridge, MA 02139, USA.
# The targets for external use include:
# all, doc, TAGS, mostlyclean, clean, distclean, realclean,
# Suppress smart makes who think they know how to automake Yacc files
.y.c:
# Variables that exist for you to override.
# See below for how to change them for certain systems.
INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
# Various ways of specifying flags for compilations:
# CFLAGS is for the user to override to, e.g., do a bootstrap with -O2.
# BOOT_CFLAGS is the value of CFLAGS to pass
# to the stage2 and stage3 compilations
# XCFLAGS is used for most compilations but not when using the GCC just built.
XCFLAGS =
CFLAGS = -g
BOOT_CFLAGS = -O $(CFLAGS)
# These exists to be overridden by the x-* and t-* files, respectively.
X_CFLAGS =
T_CFLAGS =
X_CPPFLAGS =
T_CPPFLAGS =
CC = cc
# CYGNUS LOCAL: we use byacc instead of bison, DO NOT SEND TO RMS
BISON = `if [ -f ../../byacc/byacc ] ; then echo ../../byacc/byacc ; else echo byacc ; fi`
BISONFLAGS =
LEX = `if [ -f ../../flex/flex ] ; then echo ../../flex/flex ; else echo flex ; fi`
LEXFLAGS=
AR = ar
OLDAR_FLAGS = qc
AR_FLAGS = rc
SHELL = /bin/sh
MAKEINFO = makeinfo
TEXI2DVI = texi2dvi
# Define this as & to perform parallel make on a Sequent.
# Note that this has some bugs, and it seems currently necessary
# to compile all the gen* files first by hand to avoid erroneous results.
P =
# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
# It omits XCFLAGS, and specifies -B./.
# It also specifies -B$(tooldir)/ to find as and ld for a cross compiler.
GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS)
# Tools to use when building a cross-compiler.
# These are used because `configure' appends `cross-make'
# to the makefile when making a cross-compiler.
# CYGNUS LOCAL: we don't use cross-make. Instead we use the tools
# from the build tree, if they are available.
# program_transform_name and objdir are set by configure.in.
program_transform_name =
objdir = .
target= ... `configure' substitutes actual target name here.
xmake_file= ... `configure' substitutes actual x- file name here.
tmake_file= ... `configure' substitutes actual t- file name here.
#version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < $(srcdir)/version.c`
#mainversion=`sed -e 's/.*\"\([0-9]*\.[0-9]*\).*/\1/' < $(srcdir)/version.c`
# Directory where sources are, from where we are.
srcdir = .
# Change this to a null string if obstacks are installed in the
# system library.
OBSTACK=obstack.o
# Directory to link to, when using the target `maketest'.
DIR = ../gcc
# Choose the real default target.
ALL=all
# End of variables for you to override.
# Definition of `all' is here so that new rules inserted by sed
# do not specify the default target.
all: all.indirect
# This tells GNU Make version 3 not to put all variables in the environment.
.NOEXPORT:
# sed inserts variable overrides after the following line.
####target overrides
####host overrides
####cross overrides
####build overrides
####site overrides
# Now figure out from those variables how to compile and link.
all.indirect: Makefile ../cc1plus
# IN_GCC tells obstack.h to use gstddef.h.
INTERNAL_CFLAGS = $(CROSS) -DIN_GCC
# This is the variable actually used when we compile.
ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS)
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
SUBDIR_OBSTACK = `if [ x$(OBSTACK) != x ]; then echo ../$(OBSTACK); else true; fi`
SUBDIR_USE_ALLOCA = `if [ x$(USE_ALLOCA) != x ]; then echo ../$(USE_ALLOCA); else true; fi`
SUBDIR_MALLOC = `if [ x$(MALLOC) != x ]; then echo ../$(MALLOC); else true; fi`
# How to link with both our special library facilities
# and the system's installed libraries.
LIBS = $(SUBDIR_OBSTACK) $(SUBDIR_USE_ALLOCA) $(SUBDIR_MALLOC) $(CLIB)
# Always use -I$(srcdir)/config when compiling.
.c.o:
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
# This tells GNU make version 3 not to export all the variables
# defined in this file into the environment.
.NOEXPORT:
# Lists of files for various purposes.
# Language-specific object files for g++
CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \
class.o decl2.o error.o gc.o lex.o parse.o ptree.o spew.o typeck.o cvt.o \
edsel.o except.o init.o method.o search.o tree.o xref.o
# Files specific to the C interpreter bytecode compiler(s).
BC_OBJS = ../bc-emit.o ../bc-optab.o
# Language-independent object files.
OBJS = ../toplev.o ../version.o ../tree.o ../print-tree.o ../stor-layout.o ../fold-const.o \
../function.o ../stmt.o ../expr.o ../calls.o ../expmed.o ../explow.o ../optabs.o ../varasm.o \
../rtl.o ../print-rtl.o ../rtlanal.o ../emit-rtl.o ../real.o \
../dbxout.o ../sdbout.o ../dwarfout.o ../xcoffout.o \
../integrate.o ../jump.o ../cse.o ../loop.o ../unroll.o ../flow.o ../stupid.o ../combine.o \
../regclass.o ../local-alloc.o ../global.o ../reload.o ../reload1.o ../caller-save.o \
../insn-peep.o ../reorg.o ../sched.o ../final.o ../recog.o ../reg-stack.o \
../insn-opinit.o ../insn-recog.o ../insn-extract.o ../insn-output.o ../insn-emit.o \
../insn-attrtab.o ../aux-output.o ../getpwd.o ../convert.o \
../c-common.o
compiler: ../cc1plus
../cc1plus: $(P) $(CXX_OBJS) $(OBJS) $(BC_OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o ../cc1plus \
$(CXX_OBJS) $(OBJS) $(BC_OBJS) $(LIBS)
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
cd ..; $(SHELL) config.status
native: config.status ../cc1plus
# Really, really stupid make features, such as SUN's KEEP_STATE, may force
# a target to build even if it is up-to-date. So we must verify that
# config.status does not exist before failing.
config.status:
@if [ ! -f config.status ] ; then \
echo You must configure gcc. Look at the ../INSTALL file for details.; \
false; \
else \
true; \
fi
# Compiling object files from source files.
# Note that dependencies on obstack.h are not written
# because that file is not part of GCC.
# Dependencies on gvarargs.h are not written
# because all that file does, when not compiling with GCC,
# is include the system varargs.h.
# C++ language specific files.
TREE_H = ../tree.h ../real.h ../tree.def ../machmode.h ../machmode.def
CXX_TREE_H = $(TREE_H) cp-tree.h tree.def
parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h lex.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(srcdir)/parse.c | sed 's,^\./,,'`
$(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y
@echo expect 28 shift/reduce conflicts, 14 reduce/reduce conflicts.
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h
# hash.h really depends on $(srcdir)/gxx.gperf.
# But this would screw things for people that don't have gperf,
# if gxx.gpref got touched, say.
# Thus you have to remove hash.h to force it to be re-made.
$(srcdir)/hash.h:
gperf -p -j1 -g -o -t -N is_reserved_word '-k1,4,7,$$' \
$(srcdir)/gxx.gperf >$(srcdir)/hash.h
spew.o : spew.c $(CONFIG_H) $(CXX_TREE_H) \
parse.h ../flags.h lex.h
lex.o : lex.c $(CONFIG_H) $(CXX_TREE_H) \
parse.h input.c ../flags.h hash.h lex.h
decl.o : decl.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h \
lex.h decl.h ../stack.h
decl2.o : decl2.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h \
lex.h decl.h
typeck2.o : typeck2.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h
typeck.o : typeck.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h $(RTL_H)
class.o : class.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h
call.o : call.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h class.h
init.o : init.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h $(RTL_H)
method.o : method.c $(CONFIG_H) $(CXX_TREE_H) class.h
cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) class.h
search.o : search.c $(CONFIG_H) $(CXX_TREE_H) ../stack.h ../flags.h
tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h
ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H)
gc.o : gc.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h
except.o : except.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h $(RTL_H)
expr.o : expr.c $(CONFIG_H) $(CXX_TREE_H) $(RTL_H) ../flags.h \
../expr.h ../insn-codes.h
edsel.o : edsel.c $(CONFIG_H) $(CXX_TREE_H) ../stack.h ../flags.h
xref.o : xref.c $(CONFIG_H) $(CXX_TREE_H) ../input.h
pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h parse.h
error.o : error.c $(CONFIG_H) $(CXX_TREE_H)
errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H)
sig.o : sig.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h
doc: info
info:
dvi:
# Deletion of files made during compilation.
# There are four levels of this:
# `mostlyclean', `clean', `distclean' and `realclean'.
# `mostlyclean' is useful while working on a particular type of machine.
# It deletes most, but not all, of the files made by compilation.
# It does not delete libgcc.a or its parts, so it won't have to be recompiled.
# `clean' deletes everything made by running `make all'.
# `distclean' also deletes the files made by config.
# `realclean' also deletes everything that could be regenerated automatically.
mostlyclean:
# Delete the stamp files.
-rm -f stamp-* tmp-*
# Delete debugging dump files.
-rm -f *.greg *.lreg *.combine *.flow *.cse *.jump *.rtl *.tree *.loop
-rm -f *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack
# Delete unwanted output files from TeX.
-rm -f *.toc *.log *.vr *.fn *.cp *.tp *.ky *.pg
# Delete sorted indices we don't actually use.
-rm -f gcc.vrs gcc.kys gcc.tps gcc.pgs gcc.fns
-rm -f *.o ../cc1plus
# Delete all files made by compilation
# that don't exist in the distribution.
clean: mostlyclean
-rm -f *.dvi
# Delete all files that users would normally create
# while building and installing GCC.
distclean: clean
-rm -f config.status Makefile *.oaux
-rm -f parse.output
# Delete anything likely to be found in the source directory
# that shouldn't be in the distribution.
extraclean: distclean
-rm -rf =* ./"#"* *~*
-rm -f patch* *.orig *.rej
-rm -f *.dvi *.oaux *.d *.[zZ] *.gz
-rm -f *.s *.s[0-9] *.i
# Get rid of every file that's generated from some other file.
# Most of these files ARE PRESENT in the GCC distribution.
realclean: distclean
-rm -f TAGS
-rm -f parse.c parse.h parse.output
# These exist for maintenance purposes.
# This target creates the files that can be rebuilt, but go in the
# distribution anyway.
distdir: parse.c hash.h
# Update the tags table.
TAGS: force
cd $(srcdir) ; \
etags *.c *.h ; \
echo 'l' | tr 'l' '\f' >> TAGS ; \
echo 'parse.y,0' >> TAGS ; \
etags -a ../*.h ../*.c;
.PHONY: clean realclean TAGS
force:

4205
gcc/cp/call.c Normal file

File diff suppressed because it is too large Load Diff

5048
gcc/cp/class.c Normal file

File diff suppressed because it is too large Load Diff

161
gcc/cp/class.h Normal file
View File

@ -0,0 +1,161 @@
/* Variables and structures for overloading rules.
Copyright (C) 1993 Free Software Foundation, Inc.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* The following structure is used when comparing various alternatives
for overloading. The unsigned quantity `strikes.i' is used
for fast comparison of two possibilities. This number is an
aggregate of four constituents:
EVIL: if this is non-zero, then the candidate should not be considered
ELLIPSIS: if this is non-zero, then some actual argument has been matched
against an ellipsis
USER: if this is non-zero, then a user-defined type conversion is needed
B_OR_D: if this is non-zero, then use a base pointer instead of the
type of the pointer we started with.
EASY: if this is non-zero, then we have a builtin conversion
(such as int to long, int to float, etc) to do.
If two candidates require user-defined type conversions, and the
type conversions are not identical, then an ambiguity error
is reported.
If two candidates agree on user-defined type conversions,
and one uses pointers of strictly higher type (derived where
another uses base), then that alternative is silently chosen.
If two candidates have a non-monotonic derived/base pointer
relationship, and/or a non-monotonic easy conversion relationship,
then a warning is emitted to show which paths are possible, and
which one is being chosen.
For example:
int i;
double x;
overload f;
int f (int, int);
double f (double, double);
f (i, x); // draws a warning
struct B
{
f (int);
} *bb;
struct D : B
{
f (double);
} *dd;
dd->f (x); // exact match
dd->f (i); // draws warning
Note that this technique really only works for 255 arguments. Perhaps
this is not enough. */
/* These macros and harshness_code are used by the NEW METHOD. */
#define EVIL_CODE (1<<7)
#define CONST_CODE (1<<6)
#define ELLIPSIS_CODE (1<<5)
#define USER_CODE (1<<4)
#define STD_CODE (1<<3)
#define PROMO_CODE (1<<2)
#define QUAL_CODE (1<<1)
#define TRIVIAL_CODE (1<<0)
struct harshness_code
{
/* What kind of conversion is involved. */
unsigned short code;
/* The inheritance distance. */
short distance;
/* For a PROMO_CODE, Any special penalties involved in integral conversions.
This exists because $4.1 of the ARM states that something like
`short unsigned int' should promote to `int', not `unsigned int'.
If, for example, it tries to match two fns, f(int) and f(unsigned),
f(int) should be a better match than f(unsigned) by this rule. Without
this extra metric, they both only appear as "integral promotions", which
will lead to an ambiguity.
For a TRIVIAL_CODE, This is also used by build_overload_call_real and
convert_harshness to keep track of other information we need. */
unsigned short int_penalty;
};
struct candidate
{
/* OLD METHOD */
unsigned char evil; /* !0 if this will never convert. */
unsigned char ellipsis; /* !0 if a match against an ellipsis occurred */
unsigned char user; /* !0 if at least one user-defined type conv. */
unsigned short b_or_d; /* count number of derived->base or
base->derived conv. */
unsigned short easy; /* count number of builtin type conv. */
/* NEW METHOD */
struct harshness_code h; /* Used for single-argument conversions. */
int h_len; /* The length of the harshness vector. */
/* Both methods. */
tree function; /* A FUNCTION_DECL */
tree basetypes; /* The path to function. */
tree arg; /* first parm to function. */
/* This union is only here while we maintain both the old and new
argument matching schemes. When it goes away, all v.ansi_harshness
references will be just `harshness'. */
union
{
/* Indexed by argument number, encodes evil, user, d_to_b, and easy
strikes for that argument. At end of array, we store the index+1
of where we started using default parameters, or 0 if there are
none. */
struct harshness_code *ansi_harshness; /* NEW METHOD */
unsigned short *old_harshness; /* OLD METHOD */
} v;
union
{
tree field; /* If no evil strikes, the FUNCTION_DECL of
the function (if a member function). */
int bad_arg; /* the index of the first bad argument:
0 if no bad arguments
> 0 is first bad argument
-1 if extra actual arguments
-2 if too few actual arguments.
-3 if const/non const method mismatch.
-4 if type unification failed.
-5 if contravariance violation. */
} u;
};
int rank_for_overload ();
/* Variables shared between cp-class.c and cp-call.c. */
extern int n_vtables;
extern int n_vtable_entries;
extern int n_vtable_searches;
extern int n_vtable_elems;
extern int n_convert_harshness;
extern int n_compute_conversion_costs;
extern int n_build_method_call;
extern int n_inner_fields_searched;

92
gcc/cp/cp-tree.def Normal file
View File

@ -0,0 +1,92 @@
/* This file contains the definitions and documentation for the
additional tree codes used in the GNU C++ compiler (see tree.def
for the standard codes).
Copyright (C) 1987, 1988, 1990, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Reference to the contents of an offset
(a value whose type is an OFFSET_TYPE).
Operand 0 is the object within which the offset is taken.
Operand 1 is the offset. The language independent OFFSET_REF
just won't work for us. */
DEFTREECODE (CP_OFFSET_REF, "cp_offset_ref", "r", 2)
/* For DELETE_EXPR, operand 0 is the store to be destroyed.
Operand 1 is the value to pass to the destroying function
saying whether the store should be deallocated as well. */
DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2)
/* Value is reference to particular overloaded class method.
Operand 0 is the class name (an IDENTIFIER_NODE);
operand 1 is the field (also an IDENTIFIER_NODE).
The COMPLEXITY field holds the class level (usually 0). */
DEFTREECODE (SCOPE_REF, "scope_ref", "r", 2)
/* When composing an object with a member, this is the result.
Operand 0 is the object. Operand 1 is the member (usually
a dereferenced pointer to member). */
DEFTREECODE (MEMBER_REF, "member_ref", "r", 2)
/* Type conversion operator in C++. TREE_TYPE is type that this
operator converts to. Operand is expression to be converted. */
DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1)
/* For CPLUS_NEW_EXPR, operand 0 is function which performs initialization,
operand 1 is argument list to initialization function,
and operand 2 is the slot which was allocated for this expression. */
DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3)
/* Distinguish variables that are only used to identify exceptions
that were caught. Only the DECL_NAME (and TREE_CHAIN)
is really used. */
DEFTREECODE (CPLUS_CATCH_DECL, "catch_decl", "d", 0)
/* Template definition. The following fields have the specified uses,
although there are other macros in cp-tree.h that should be used for
accessing this data.
DECL_ARGUMENTS template parm vector
DECL_TEMPLATE_INFO template text &c
DECL_VINDEX list of instantiations already produced;
only done for functions so far
For class template:
DECL_INITIAL associated templates (methods &c)
DECL_RESULT null
For non-class templates:
TREE_TYPE type of object to be constructed
DECL_RESULT decl for object to be created
(e.g., FUNCTION_DECL with tmpl parms used)
*/
DEFTREECODE (TEMPLATE_DECL, "template_decl", "d", 0)
/* Index into a template parameter list. This parameter must be a type.
Use TYPE_FIELDS to find parmlist and index. */
DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", "t", 0)
/* Index into a template parameter list. This parameter must not be a
type. */
DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 2)
/* For uninstantiated parameterized types.
TYPE_VALUES tree list:
TREE_PURPOSE template decl
TREE_VALUE parm vector
TREE_CHAIN null
Other useful fields to be defined later. */
DEFTREECODE (UNINSTANTIATED_P_TYPE, "uninstantiated_p_type", "t", 0)

2228
gcc/cp/cp-tree.h Normal file

File diff suppressed because it is too large Load Diff

1997
gcc/cp/cvt.c Normal file

File diff suppressed because it is too large Load Diff

12087
gcc/cp/decl.c Normal file

File diff suppressed because it is too large Load Diff

59
gcc/cp/decl.h Normal file
View File

@ -0,0 +1,59 @@
/* Variables and structures for declaration processing.
Copyright (C) 1993 Free Software Foundation, Inc.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
{ NORMAL, /* Ordinary declaration */
FUNCDEF, /* Function definition */
PARM, /* Declaration of parm before function body */
FIELD, /* Declaration inside struct or union */
BITFIELD, /* Likewise but with specified width */
TYPENAME, /* Typename (inside cast or sizeof) */
MEMFUNCDEF /* Member function definition */
};
/* C++: Keep these around to reduce calls to `get_identifier'.
Identifiers for `this' in member functions and the auto-delete
parameter for destructors. */
extern tree this_identifier, in_charge_identifier;
/* Parsing a function declarator leaves a list of parameter names
or a chain or parameter decls here. */
extern tree last_function_parms;
/* 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. */
extern tree pending_statics;
/* 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. */
extern tree static_aggregates;
/* A list of functions which were declared inline, but later had their
address taken. Used only for non-virtual member functions, since we can
find other functions easily enough. */
extern tree pending_addressable_inlines;
#ifdef DEBUG_CP_BINDING_LEVELS
/* Purely for debugging purposes. */
extern int debug_bindings_indentation;
#endif

2823
gcc/cp/decl2.c Normal file

File diff suppressed because it is too large Load Diff

217
gcc/cp/errfn.c Normal file
View File

@ -0,0 +1,217 @@
/* Provide a call-back mechanism for handling error output.
Copyright (C) 1993 Free Software Foundation, Inc.
Contributed 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "tree.h"
#include <ctype.h>
/* cp_printer is the type of a function which converts an argument into
a string for digestion by printf. The cp_printer function should deal
with all memory management; the functions in this file will not free
the char*s returned. See cp-error.c for an example use of this code. */
typedef char* cp_printer PROTO((HOST_WIDE_INT, int));
extern cp_printer * cp_printers[256];
typedef void errorfn (); /* deliberately vague */
extern char* cp_file_of PROTO((tree));
extern int cp_line_of PROTO((tree));
#define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
#define NARGS 3
#define arglist a1, a2, a3
#define arglist_dcl HOST_WIDE_INT a1, a2, a3;
#define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3;
#define ARGSLIST args[0], args[1], args[2]
static void
cp_thing (errfn, atarg1, format, arglist)
errorfn *errfn;
int atarg1;
char *format;
arglist_dcl
{
char *fmt;
char *f;
char *ap;
int arg;
HOST_WIDE_INT atarg = atarg1 ? a1 : 0;
HOST_WIDE_INT args[NARGS];
ARGSINIT
fmt = STRDUP(format);
for (f = fmt, arg = 0; *f; ++f)
{
cp_printer * function;
int alternate;
int maybe_here;
/* ignore text */
if (*f != '%') continue;
++f;
alternate = 0;
maybe_here = 0;
/* ignore most flags */
while (*f == ' ' || *f == '-' || *f == '+' || *f == '#')
{
if (*f == '+')
maybe_here = 1;
else if (*f == '#')
alternate = 1;
++f;
}
/* ignore field width */
if (*f == '*')
{
++f;
++arg;
}
else
while (isdigit (*f))
++f;
/* ignore precision */
if (*f == '.')
{
++f;
if (*f == '*')
{
++f;
++arg;
}
else
while (isdigit (*f))
++f;
}
/* ignore "long" */
if (*f == 'l')
++f;
function = cp_printers[*f];
if (function)
{
char *p;
if (arg >= NARGS) abort ();
if (maybe_here && atarg)
atarg = args[arg];
/* Must use a temporary to avoid calling *function twice */
p = (*function) (args[arg], alternate);
args[arg] = (HOST_WIDE_INT) STRDUP(p);
*f = 's';
}
++arg; /* Assume valid format string */
}
if (atarg)
{
char *file = cp_file_of ((tree) atarg);
int line = cp_line_of ((tree) atarg);
(*errfn) (file, line, fmt, ARGSLIST);
}
else
(*errfn) (fmt, ARGSLIST);
}
void
cp_error (format, arglist)
char *format;
arglist_dcl
{
extern errorfn error;
cp_thing (error, 0, format, arglist);
}
void
cp_warning (format, arglist)
char *format;
arglist_dcl
{
extern errorfn warning;
cp_thing (warning, 0, format, arglist);
}
void
cp_pedwarn (format, arglist)
char *format;
arglist_dcl
{
extern errorfn pedwarn;
cp_thing (pedwarn, 0, format, arglist);
}
void
cp_compiler_error (format, arglist)
char *format;
arglist_dcl
{
extern errorfn compiler_error;
cp_thing (compiler_error, 0, format, arglist);
}
void
cp_sprintf (format, arglist)
char *format;
arglist_dcl
{
extern errorfn sprintf;
cp_thing (sprintf, 0, format, arglist);
}
void
cp_error_at (format, arglist)
char *format;
arglist_dcl
{
extern errorfn error_with_file_and_line;
cp_thing (error_with_file_and_line, 1, format, arglist);
}
void
cp_warning_at (format, arglist)
char *format;
arglist_dcl
{
extern errorfn warning_with_file_and_line;
cp_thing (warning_with_file_and_line, 1, format, arglist);
}
void
cp_pedwarn_at (format, arglist)
char *format;
arglist_dcl
{
extern errorfn pedwarn_with_file_and_line;
cp_thing (pedwarn_with_file_and_line, 1, format, arglist);
}

1339
gcc/cp/error.c Normal file

File diff suppressed because it is too large Load Diff

1224
gcc/cp/except.c Normal file

File diff suppressed because it is too large Load Diff

268
gcc/cp/expr.c Normal file
View File

@ -0,0 +1,268 @@
/* Convert language-specific tree expression to rtl instructions,
for GNU compiler.
Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
#include "expr.h"
#include "cp-tree.h"
#undef NULL
#define NULL 0
/* Hook used by expand_expr to expand language-specific tree codes. */
rtx
cplus_expand_expr (exp, target, tmode, modifier)
tree exp;
rtx target;
enum machine_mode tmode;
enum expand_modifier modifier;
{
tree type = TREE_TYPE (exp);
register enum machine_mode mode = TYPE_MODE (type);
register enum tree_code code = TREE_CODE (exp);
rtx original_target = target;
int ignore = target == const0_rtx;
if (ignore)
target = 0, original_target = 0;
/* No sense saving up arithmetic to be done
if it's all in the wrong mode to form part of an address.
And force_operand won't know whether to sign-extend or zero-extend. */
if (mode != Pmode && modifier == EXPAND_SUM)
modifier = EXPAND_NORMAL;
switch (code)
{
case NEW_EXPR:
{
/* Something needs to be initialized, but we didn't know
where that thing was when building the tree. For example,
it could be the return value of a function, or a parameter
to a function which lays down in the stack, or a temporary
variable which must be passed by reference.
Cleanups are handled in a language-specific way: they
might be run by the called function (true in GNU C++
for parameters with cleanups), or they might be
run by the caller, after the call (true in GNU C++
for other cleanup needs). */
tree func = TREE_OPERAND (exp, 0);
tree args = TREE_OPERAND (exp, 1);
tree type = TREE_TYPE (exp), slot;
tree fn_type = TREE_TYPE (TREE_TYPE (func));
tree return_type = TREE_TYPE (fn_type);
tree call_exp;
rtx call_target, return_target;
int pcc_struct_return = 0;
/* The expression `init' wants to initialize what
`target' represents. SLOT holds the slot for TARGET. */
slot = TREE_OPERAND (exp, 2);
if (target == 0)
{
/* Should always be called with a target in BLKmode case. */
my_friendly_assert (mode != BLKmode, 205);
my_friendly_assert (DECL_RTL (slot) != 0, 206);
target = gen_reg_rtx (mode);
}
/* The target the initializer will initialize (CALL_TARGET)
must now be directed to initialize the target we are
supposed to initialize (TARGET). The semantics for
choosing what CALL_TARGET is is language-specific,
as is building the call which will perform the
initialization. It is left here to show the choices that
exist for C++. */
if (TREE_CODE (func) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
{
type = TYPE_POINTER_TO (type);
/* Don't clobber a value that might be part of a default
parameter value. */
if (TREE_PERMANENT (args))
args = tree_cons (0, build1 (ADDR_EXPR, type, slot),
TREE_CHAIN (args));
else
TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot);
call_target = 0;
}
else if (TREE_CODE (return_type) == REFERENCE_TYPE)
{
type = return_type;
call_target = 0;
}
else
{
#ifdef PCC_STATIC_STRUCT_RETURN
pcc_struct_return = 1;
call_target = 0;
#else
call_target = target;
#endif
}
if (call_target)
{
preserve_temp_slots (call_target);
/* Make this a valid memory address now. The code below assumes
that it can compare rtx and make assumptions based on the
result. The assumptions are true only if the address was
valid to begin with. */
call_target = validize_mem (call_target);
}
preserve_temp_slots (DECL_RTL (slot));
call_exp = build (CALL_EXPR, type, func, args, 0);
TREE_SIDE_EFFECTS (call_exp) = 1;
return_target = expand_expr (call_exp, call_target, mode, 0);
free_temp_slots ();
if (call_target == 0)
{
if (pcc_struct_return)
{
tree init = build (RTL_EXPR, type, 0, return_target);
TREE_ADDRESSABLE (init) = 1;
expand_aggr_init (slot, init, 0);
if (TYPE_NEEDS_DESTRUCTOR (type))
{
init = build (RTL_EXPR, build_reference_type (type), 0,
XEXP (return_target, 0));
init = maybe_build_cleanup (convert_from_reference (init));
if (init != NULL_TREE)
expand_expr (init, 0, 0, 0);
}
call_target = return_target = DECL_RTL (slot);
}
else
call_target = return_target;
}
if (call_target != return_target)
{
my_friendly_assert (! TYPE_NEEDS_CONSTRUCTING (type), 317);
if (GET_MODE (return_target) == BLKmode)
emit_block_move (call_target, return_target, expr_size (exp),
TYPE_ALIGN (type) / BITS_PER_UNIT);
else
emit_move_insn (call_target, return_target);
}
if (TREE_CODE (return_type) == REFERENCE_TYPE)
{
tree init;
if (GET_CODE (call_target) == REG
&& REGNO (call_target) < FIRST_PSEUDO_REGISTER)
my_friendly_abort (39);
type = TREE_TYPE (exp);
init = build (RTL_EXPR, return_type, 0, call_target);
/* We got back a reference to the type we want. Now initialize
target with that. */
expand_aggr_init (slot, init, 0);
}
if (DECL_RTL (slot) != target)
emit_move_insn (DECL_RTL (slot), target);
return DECL_RTL (slot);
}
case OFFSET_REF:
{
#if 1
return expand_expr (default_conversion (resolve_offset_ref (exp)),
target, tmode, EXPAND_NORMAL);
#else
/* This is old crusty code, and does not handle all that the
resolve_offset_ref function does. (mrs) */
tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
target, tmode, EXPAND_NORMAL);
#endif
}
default:
break;
}
my_friendly_abort (40);
/* NOTREACHED */
return NULL;
}
void
init_cplus_expand ()
{
lang_expand_expr = cplus_expand_expr;
}
/* If DECL had its rtl moved from where callers expect it
to be, fix it up. RESULT is the nominal rtl for the RESULT_DECL,
which may be a pseudo instead of a hard register. */
void
fixup_result_decl (decl, result)
tree decl;
rtx result;
{
if (REG_P (result))
{
if (REGNO (result) >= FIRST_PSEUDO_REGISTER)
{
rtx real_decl_result;
#ifdef FUNCTION_OUTGOING_VALUE
real_decl_result
= FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl), current_function_decl);
#else
real_decl_result
= FUNCTION_VALUE (TREE_TYPE (decl), current_function_decl);
#endif
REG_FUNCTION_VALUE_P (real_decl_result) = 1;
result = real_decl_result;
}
emit_move_insn (result, DECL_RTL (decl));
emit_insn (gen_rtx (USE, VOIDmode, result));
}
}
/* Return nonzero 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. */
int
decl_in_memory_p (decl)
tree decl;
{
return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
}

91
gcc/cp/gxx.gperf Normal file
View File

@ -0,0 +1,91 @@
%{
/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
%}
struct resword { char *name; short token; enum rid rid;};
%%
__alignof, ALIGNOF, NORID
__alignof__, ALIGNOF, NORID
__asm, GCC_ASM_KEYWORD, NORID
__asm__, GCC_ASM_KEYWORD, NORID
__attribute, ATTRIBUTE, NORID
__attribute__, ATTRIBUTE, NORID
__classof, CLASSOF, NORID
__classof__, CLASSOF, NORID
__const, TYPE_QUAL, RID_CONST
__const__, TYPE_QUAL, RID_CONST
__extension__, EXTENSION, NORID
__headof, HEADOF, NORID
__headof__, HEADOF, NORID
__inline, SCSPEC, RID_INLINE
__inline__, SCSPEC, RID_INLINE
__label__, LABEL, NORID
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
__typeof, TYPEOF, NORID
__typeof__, TYPEOF, NORID
__volatile, TYPE_QUAL, RID_VOLATILE
__volatile__, TYPE_QUAL, RID_VOLATILE
__wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,
all, ALL, NORID /* Extension */,
except, EXCEPT, NORID /* Extension */,
exception, AGGR, RID_EXCEPTION /* Extension */,
raise, RAISE, NORID /* Extension */,
raises, RAISES, NORID /* Extension */,
reraise, RERAISE, NORID /* Extension */,
throw, THROW, NORID /* Extension */,
try, TRY, NORID /* Extension */,
asm, ASM_KEYWORD, NORID,
auto, SCSPEC, RID_AUTO,
break, BREAK, NORID,
case, CASE, NORID,
catch, CATCH, NORID,
char, TYPESPEC, RID_CHAR,
class, AGGR, RID_CLASS,
classof, CLASSOF, NORID,
const, TYPE_QUAL, RID_CONST,
continue, CONTINUE, NORID,
default, DEFAULT, NORID,
delete, DELETE, NORID,
do, DO, NORID,
double, TYPESPEC, RID_DOUBLE,
dynamic_cast, DYNAMIC_CAST, NORID,
else, ELSE, NORID,
enum, ENUM, NORID,
extern, SCSPEC, RID_EXTERN,
float, TYPESPEC, RID_FLOAT,
for, FOR, NORID,
friend, SCSPEC, RID_FRIEND,
goto, GOTO, NORID,
headof, HEADOF, NORID,
if, IF, NORID,
inline, SCSPEC, RID_INLINE,
int, TYPESPEC, RID_INT,
long, TYPESPEC, RID_LONG,
mutable, SCSPEC, RID_MUTABLE,
new, NEW, NORID,
operator, OPERATOR, NORID,
overload, OVERLOAD, NORID,
private, VISSPEC, RID_PRIVATE,
protected, VISSPEC, RID_PROTECTED,
public, VISSPEC, RID_PUBLIC,
register, SCSPEC, RID_REGISTER,
return, RETURN, NORID,
short, TYPESPEC, RID_SHORT,
signature, AGGR, RID_SIGNATURE /* Extension */,
signed, TYPESPEC, RID_SIGNED,
sigof, SIGOF, NORID /* Extension */,
sizeof, SIZEOF, NORID,
static, SCSPEC, RID_STATIC,
struct, AGGR, RID_RECORD,
switch, SWITCH, NORID,
this, THIS, NORID,
template, TEMPLATE, NORID,
typedef, SCSPEC, RID_TYPEDEF,
typeof, TYPEOF, NORID,
typeid, TYPEID, NORID,
union, AGGR, RID_UNION,
unsigned, TYPESPEC, RID_UNSIGNED,
virtual, SCSPEC, RID_VIRTUAL,
void, TYPESPEC, RID_VOID,
volatile, TYPE_QUAL, RID_VOLATILE,
while, WHILE, NORID,

1030
gcc/cp/gxxint.texi Normal file

File diff suppressed because it is too large Load Diff

207
gcc/cp/hash.h Normal file
View File

@ -0,0 +1,207 @@
/* C code produced by gperf version 2.5 (GNU C++ version) */
/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,7,$ ../../../devo/gcc/cp/gxx.gperf */
/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
struct resword { char *name; short token; enum rid rid;};
#define TOTAL_KEYWORDS 86
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 13
#define MIN_HASH_VALUE 4
#define MAX_HASH_VALUE 196
/* maximum key range = 193, duplicates = 0 */
#ifdef __GNUC__
inline
#endif
static unsigned int
hash (str, len)
register char *str;
register int unsigned len;
{
static unsigned char asso_values[] =
{
197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 0, 197, 93, 3, 35,
3, 0, 71, 8, 4, 78, 197, 3, 30, 6,
29, 18, 37, 197, 55, 0, 4, 11, 7, 20,
0, 8, 197, 197, 197, 197, 197, 197,
};
register int hval = len;
switch (hval)
{
default:
case 7:
hval += asso_values[str[6]];
case 6:
case 5:
case 4:
hval += asso_values[str[3]];
case 3:
case 2:
case 1:
hval += asso_values[str[0]];
}
return hval + asso_values[str[len - 1]];
}
#ifdef __GNUC__
inline
#endif
struct resword *
is_reserved_word (str, len)
register char *str;
register unsigned int len;
{
static struct resword wordlist[] =
{
{"",}, {"",}, {"",}, {"",},
{"else", ELSE, NORID,},
{"",}, {"",},
{"__asm__", GCC_ASM_KEYWORD, NORID},
{"this", THIS, NORID,},
{"delete", DELETE, NORID,},
{"except", EXCEPT, NORID /* Extension */,},
{"__asm", GCC_ASM_KEYWORD, NORID},
{"double", TYPESPEC, RID_DOUBLE,},
{"typeid", TYPEID, NORID,},
{"switch", SWITCH, NORID,},
{"try", TRY, NORID /* Extension */,},
{"enum", ENUM, NORID,},
{"void", TYPESPEC, RID_VOID,},
{"",}, {"",}, {"",},
{"struct", AGGR, RID_RECORD,},
{"",},
{"do", DO, NORID,},
{"",}, {"",}, {"",}, {"",},
{"__headof__", HEADOF, NORID},
{"",}, {"",},
{"__const__", TYPE_QUAL, RID_CONST},
{"__volatile", TYPE_QUAL, RID_VOLATILE},
{"__const", TYPE_QUAL, RID_CONST},
{"__volatile__", TYPE_QUAL, RID_VOLATILE},
{"extern", SCSPEC, RID_EXTERN,},
{"__typeof__", TYPEOF, NORID},
{"",},
{"signed", TYPESPEC, RID_SIGNED,},
{"case", CASE, NORID,},
{"class", AGGR, RID_CLASS,},
{"__classof__", CLASSOF, NORID},
{"__extension__", EXTENSION, NORID},
{"",},
{"const", TYPE_QUAL, RID_CONST,},
{"static", SCSPEC, RID_STATIC,},
{"",},
{"throw", THROW, NORID /* Extension */,},
{"goto", GOTO, NORID,},
{"signature", AGGR, RID_SIGNATURE /* Extension */,},
{"long", TYPESPEC, RID_LONG,},
{"private", VISSPEC, RID_PRIVATE,},
{"new", NEW, NORID,},
{"template", TEMPLATE, NORID,},
{"",},
{"while", WHILE, NORID,},
{"",},
{"protected", VISSPEC, RID_PROTECTED,},
{"continue", CONTINUE, NORID,},
{"",},
{"raise", RAISE, NORID /* Extension */,},
{"raises", RAISES, NORID /* Extension */,},
{"",},
{"union", AGGR, RID_UNION,},
{"short", TYPESPEC, RID_SHORT,},
{"",},
{"__inline", SCSPEC, RID_INLINE},
{"",},
{"__inline__", SCSPEC, RID_INLINE},
{"",},
{"__alignof__", ALIGNOF, NORID},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"sizeof", SIZEOF, NORID,},
{"virtual", SCSPEC, RID_VIRTUAL,},
{"catch", CATCH, NORID,},
{"friend", SCSPEC, RID_FRIEND,},
{"typeof", TYPEOF, NORID,},
{"",}, {"",},
{"headof", HEADOF, NORID,},
{"int", TYPESPEC, RID_INT,},
{"",}, {"",},
{"__signed__", TYPESPEC, RID_SIGNED},
{"__signed", TYPESPEC, RID_SIGNED},
{"",}, {"",}, {"",},
{"__attribute", ATTRIBUTE, NORID},
{"sigof", SIGOF, NORID /* Extension */,},
{"__attribute__", ATTRIBUTE, NORID},
{"",},
{"__headof", HEADOF, NORID},
{"",}, {"",},
{"unsigned", TYPESPEC, RID_UNSIGNED,},
{"return", RETURN, NORID,},
{"asm", ASM_KEYWORD, NORID,},
{"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,},
{"break", BREAK, NORID,},
{"__typeof", TYPEOF, NORID},
{"mutable", SCSPEC, RID_MUTABLE,},
{"",},
{"public", VISSPEC, RID_PUBLIC,},
{"",},
{"__classof", CLASSOF, NORID},
{"default", DEFAULT, NORID,},
{"",}, {"",}, {"",}, {"",},
{"exception", AGGR, RID_EXCEPTION /* Extension */,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"all", ALL, NORID /* Extension */,},
{"",}, {"",},
{"for", FOR, NORID,},
{"",}, {"",},
{"__label__", LABEL, NORID},
{"auto", SCSPEC, RID_AUTO,},
{"",}, {"",}, {"",}, {"",},
{"volatile", TYPE_QUAL, RID_VOLATILE,},
{"__alignof", ALIGNOF, NORID},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"dynamic_cast", DYNAMIC_CAST, NORID,},
{"",},
{"char", TYPESPEC, RID_CHAR,},
{"",},
{"if", IF, NORID,},
{"",},
{"typedef", SCSPEC, RID_TYPEDEF,},
{"operator", OPERATOR, NORID,},
{"reraise", RERAISE, NORID /* Extension */,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"inline", SCSPEC, RID_INLINE,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",},
{"float", TYPESPEC, RID_FLOAT,},
{"",}, {"",}, {"",},
{"overload", OVERLOAD, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"classof", CLASSOF, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",},
{"register", SCSPEC, RID_REGISTER,},
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register int key = hash (str, len);
if (key <= MAX_HASH_VALUE && key >= 0)
{
register char *s = wordlist[key].name;
if (*s == *str && !strcmp (str + 1, s + 1))
return &wordlist[key];
}
}
return 0;
}

4181
gcc/cp/init.c Normal file

File diff suppressed because it is too large Load Diff

184
gcc/cp/input.c Normal file
View File

@ -0,0 +1,184 @@
/* Input handling for G++.
Copyright (C) 1992, 1993 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* G++ needs to do enough saving and re-parsing of text that it is
necessary to abandon the simple FILE* model and use a mechanism where
we can pre-empt one input stream with another derived from saved text;
we may need to do this arbitrarily often, and cannot depend on having
the GNU library available, so FILE objects just don't cut it.
This file is written as a separate module, but can be included by
cp-lex.c for very minor efficiency gains (primarily in function
inlining). */
#include <stdio.h>
#include "obstack.h"
extern FILE *finput;
struct pending_input *save_pending_input ();
void restore_pending_input ();
struct input_source {
/* saved string */
char *str;
int length;
/* current position, when reading as input */
int offset;
/* obstack to free this input string from when finished, if any */
struct obstack *obstack;
/* linked list maintenance */
struct input_source *next;
/* values to restore after reading all of current string */
char *filename;
int lineno;
struct pending_input *input;
int putback_char;
};
static struct input_source *input, *free_inputs;
extern char *input_filename;
extern int lineno;
#ifdef __GNUC__
#define inline __inline__
#else
#define inline
#endif
static inline struct input_source *
allocate_input ()
{
struct input_source *inp;
if (free_inputs)
{
inp = free_inputs;
free_inputs = inp->next;
inp->next = 0;
return inp;
}
inp = (struct input_source *) xmalloc (sizeof (struct input_source));
inp->next = 0;
inp->obstack = 0;
return inp;
}
static inline void
free_input (inp)
struct input_source *inp;
{
if (inp->obstack)
obstack_free (inp->obstack, inp->str);
inp->obstack = 0;
inp->str = 0;
inp->length = 0;
inp->next = free_inputs;
free_inputs = inp;
}
static int putback_char = -1;
/* Some of these external functions are declared inline in case this file
is included in cp-lex.c. */
inline
void
feed_input (str, len, delete)
char *str;
int len;
struct obstack *delete;
{
struct input_source *inp = allocate_input ();
/* This shouldn't be necessary. */
while (len && !str[len-1])
len--;
inp->str = str;
inp->length = len;
inp->obstack = delete;
inp->offset = 0;
inp->next = input;
inp->filename = input_filename;
inp->lineno = lineno;
inp->input = save_pending_input ();
inp->putback_char = putback_char;
putback_char = -1;
input = inp;
}
struct pending_input *to_be_restored; /* XXX */
extern int end_of_file;
int
getch ()
{
if (putback_char != -1)
{
int ch = putback_char;
putback_char = -1;
return ch;
}
if (input)
{
if (input->offset == input->length)
{
struct input_source *inp = input;
my_friendly_assert (putback_char == -1, 223);
to_be_restored = inp->input;
input->offset++;
return EOF;
}
else if (input->offset > input->length)
{
struct input_source *inp = input;
end_of_file = 0;
input = inp->next;
input_filename = inp->filename;
lineno = inp->lineno;
/* Get interface/implementation back in sync. */
extract_interface_info ();
putback_char = inp->putback_char;
free_input (inp);
return getch ();
}
if (input)
return input->str[input->offset++];
}
return getc (finput);
}
inline
void
put_back (ch)
int ch;
{
my_friendly_assert (putback_char == -1, 224);
putback_char = ch;
}
inline
int
input_redirected ()
{
return input != 0;
}

4783
gcc/cp/lex.c Normal file

File diff suppressed because it is too large Load Diff

124
gcc/cp/lex.h Normal file
View File

@ -0,0 +1,124 @@
/* Define constants and variables for communication with cp-parse.y.
Copyright (C) 1987, 1992, 1993 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
and by Brendan Kehoe (brendan@cygnus.com).
This file is part of GNU CC.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY. No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing. Refer to the GNU CC General Public
License for full details.
Everyone is granted permission to copy, modify and redistribute
GNU CC, but only under the conditions described in the
GNU CC General Public License. A copy of this license is
supposed to have been given to you along with GNU CC so you
can know your rights and responsibilities. It should be in a
file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
enum rid
{
RID_UNUSED,
RID_INT,
RID_CHAR,
RID_WCHAR,
RID_FLOAT,
RID_DOUBLE,
RID_VOID,
/* C++ extension */
RID_CLASS,
RID_RECORD,
RID_UNION,
RID_ENUM,
RID_LONGLONG,
/* This is where grokdeclarator starts its search when setting the specbits.
The first seven are in the order of most frequently used, as found
building libg++. */
RID_EXTERN,
RID_CONST,
RID_LONG,
RID_TYPEDEF,
RID_UNSIGNED,
RID_SHORT,
RID_INLINE,
RID_STATIC,
RID_REGISTER,
RID_VOLATILE,
RID_FRIEND,
RID_VIRTUAL,
RID_PUBLIC,
RID_PRIVATE,
RID_PROTECTED,
RID_SIGNED,
RID_EXCEPTION,
RID_RAISES,
RID_AUTO,
RID_MUTABLE,
RID_SIGNATURE,
/* Before adding enough to get up to 64, the RIDBIT_* macros
will have to be changed a little. */
RID_MAX
};
#define NORID RID_UNUSED
#define RID_FIRST_MODIFIER RID_EXTERN
/* The type that can represent all values of RIDBIT. */
/* We assume that we can stick in at least 32 bits into this. */
typedef struct { unsigned long idata[2]; }
RID_BIT_TYPE;
/* Be careful, all these modify N twice. */
#define RIDBIT_SETP(N, V) (((unsigned long)1 << (int) ((N)%32)) \
& (V).idata[(N)/32])
#define RIDBIT_NOTSETP(NN, VV) (! RIDBIT_SETP (NN, VV))
#define RIDBIT_SET(N, V) do { \
(V).idata[(N)/32] \
|= ((unsigned long)1 << (int) ((N)%32)); \
} while (0)
#define RIDBIT_RESET(N, V) do { \
(V).idata[(N)/32] \
&= ~((unsigned long)1 << (int) ((N)%32)); \
} while (0)
#define RIDBIT_RESET_ALL(V) do { \
(V).idata[0] = 0; \
(V).idata[1] = 0; \
} while (0)
#define RIDBIT_ANY_SET(V) ((V).idata[0] || (V).idata[1])
/* The elements of `ridpointers' are identifier nodes
for the reserved type names and storage classes.
It is indexed by a RID_... value. */
extern tree ridpointers[(int) RID_MAX];
/* the declaration found for the last IDENTIFIER token read in.
yylex must look this up to detect typedefs, which get token type TYPENAME,
so it is left around in case the identifier is not a typedef but is
used in a context which makes it a reference to a variable. */
extern tree lastiddecl;
extern char *token_buffer; /* Pointer to token buffer. */
/* Back-door communication channel to the lexer. */
extern int looking_for_typename;
/* Pending language change.
Positive is push count, negative is pop count. */
extern int pending_lang_change;
extern tree make_pointer_declarator (), make_reference_declarator ();
extern void reinit_parse_for_function ();
extern void reinit_parse_for_method ();
extern int yylex ();

1651
gcc/cp/method.c Normal file

File diff suppressed because it is too large Load Diff

4099
gcc/cp/parse.y Normal file

File diff suppressed because it is too large Load Diff

2311
gcc/cp/pt.c Normal file

File diff suppressed because it is too large Load Diff

163
gcc/cp/ptree.c Normal file
View File

@ -0,0 +1,163 @@
/* Prints out trees in human readable form.
Copyright (C) 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "tree.h"
#include <stdio.h>
#include "cp-tree.h"
void
print_lang_decl (file, node, indent)
FILE *file;
tree node;
int indent;
{
if (!DECL_LANG_SPECIFIC (node))
return;
/* A FIELD_DECL only has the flags structure, which we aren't displaying
anyways. */
if (DECL_MUTABLE_P (node))
{
indent_to (file, indent + 3);
fprintf (file, " mutable ");
}
if (TREE_CODE (node) == FIELD_DECL)
return;
indent_to (file, indent + 3);
if (DECL_MAIN_VARIANT (node))
{
fprintf (file, " decl-main-variant ");
fprintf (file, HOST_PTR_PRINTF, DECL_MAIN_VARIANT (node));
}
if (DECL_PENDING_INLINE_INFO (node))
{
fprintf (file, " pending-inline-info ");
fprintf (file, HOST_PTR_PRINTF, DECL_PENDING_INLINE_INFO (node));
}
if (DECL_TEMPLATE_INFO (node))
{
fprintf (file, " template-info ");
fprintf (file, HOST_PTR_PRINTF, DECL_TEMPLATE_INFO (node));
}
}
void
print_lang_type (file, node, indent)
FILE *file;
register tree node;
int indent;
{
if (TREE_CODE (node) == TEMPLATE_TYPE_PARM)
{
print_node (file, "tinfo", TYPE_VALUES (node), indent + 4);
return;
}
if (TREE_CODE (node) == UNINSTANTIATED_P_TYPE)
{
print_node (file, "template", UPT_TEMPLATE (node), indent + 4);
print_node (file, "parameters", UPT_PARMS (node), indent + 4);
return;
}
if (! (TREE_CODE (node) == RECORD_TYPE
|| TREE_CODE (node) == UNION_TYPE))
return;
if (!TYPE_LANG_SPECIFIC (node))
return;
indent_to (file, indent + 3);
if (TYPE_NEEDS_CONSTRUCTING (node))
fputs ( "needs-constructor", file);
if (TYPE_NEEDS_DESTRUCTOR (node))
fputs (" needs-destructor", file);
if (TYPE_HAS_DESTRUCTOR (node))
fputs (" ~X()", file);
if (TYPE_HAS_DEFAULT_CONSTRUCTOR (node))
fputs (" X()", file);
if (TYPE_HAS_CONVERSION (node))
fputs (" has-type-conversion", file);
if (TYPE_HAS_INT_CONVERSION (node))
fputs (" has-int-conversion", file);
if (TYPE_HAS_REAL_CONVERSION (node))
fputs (" has-float-conversion", file);
if (TYPE_HAS_INIT_REF (node))
{
if (TYPE_HAS_CONST_INIT_REF (node))
fputs (" X(constX&)", file);
else
fputs (" X(X&)", file);
}
if (TREE_GETS_NEW (node))
fputs (" gets-new", file);
if (TREE_GETS_DELETE (node))
fputs (" gets-delete", file);
if (TYPE_HAS_ASSIGNMENT (node))
fputs (" has=", file);
if (TYPE_HAS_ASSIGN_REF (node))
fputs (" this=(X&)", file);
if (TYPE_OVERLOADS_METHOD_CALL_EXPR (node))
fputs (" op->()", file);
if (TYPE_GETS_INIT_AGGR (node))
fputs (" gets X(X, ...)", file);
if (TYPE_OVERLOADS_CALL_EXPR (node))
fputs (" op()", file);
if (TYPE_OVERLOADS_ARRAY_REF (node))
fputs (" op[]", file);
if (TYPE_OVERLOADS_ARROW (node))
fputs (" op->", file);
if (TYPE_USES_MULTIPLE_INHERITANCE (node))
fputs (" uses-multiple-inheritance", file);
if (TREE_CODE (node) == RECORD_TYPE)
{
fprintf (file, " n_parents %d n_ancestors %d",
CLASSTYPE_N_BASECLASSES (node),
CLASSTYPE_N_SUPERCLASSES (node));
fprintf (file, " use_template=%d", CLASSTYPE_USE_TEMPLATE (node));
if (CLASSTYPE_INTERFACE_ONLY (node))
fprintf (file, " interface-only");
if (CLASSTYPE_INTERFACE_UNKNOWN (node))
fprintf (file, " interface-unknown");
print_node (file, "member-functions", CLASSTYPE_METHOD_VEC (node),
indent + 4);
print_node (file, "baselinks",
TYPE_BINFO_BASETYPES (node) ? CLASSTYPE_BASELINK_VEC (node) : NULL_TREE,
indent + 4);
}
}
void
print_lang_identifier (file, node, indent)
FILE *file;
tree node;
int indent;
{
print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
}

3308
gcc/cp/search.c Normal file

File diff suppressed because it is too large Load Diff

998
gcc/cp/sig.c Normal file
View File

@ -0,0 +1,998 @@
/* Functions dealing with signatures and signature pointers/references.
Copyright (C) 1992 Free Software Foundation, Inc.
Contributed by Gerald Baumgartner (gb@cs.purdue.edu)
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include <stdio.h>
#include "obstack.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
#include "assert.h"
extern struct obstack *current_obstack;
extern struct obstack permanent_obstack;
extern struct obstack *saveable_obstack;
extern void error ();
extern void sorry ();
extern void compiler_error ();
extern void make_decl_rtl PROTO((tree, char *, int));
/* Used to help generate globally unique names for signature tables. */
static int global_sigtable_name_counter;
/* Build an identifier for a signature pointer or reference, so we
can use it's name in function name mangling. */
static tree
build_signature_pointer_or_reference_name (to_type, constp, volatilep, refp)
tree to_type;
int constp, volatilep, refp;
{
char * sig_name = TYPE_NAME_STRING (to_type);
int name_len = TYPE_NAME_LENGTH (to_type) + constp + volatilep;
char * name;
if (refp)
{
name = (char *) alloca (name_len + sizeof (SIGNATURE_REFERENCE_NAME) +2);
sprintf (name, SIGNATURE_REFERENCE_NAME_FORMAT,
constp ? "C" : "", volatilep ? "V": "", sig_name);
}
else
{
name = (char *) alloca (name_len + sizeof (SIGNATURE_POINTER_NAME) + 2);
sprintf (name, SIGNATURE_POINTER_NAME_FORMAT,
constp ? "C" : "", volatilep ? "V": "", sig_name);
}
return get_identifier (name);
}
/* Build a DECL node for a signature pointer or reference, so we can
tell the debugger the structure of signature pointers/references.
This function is called at most eight times for a given signature,
once for each [const] [volatile] signature pointer/reference. */
static void
build_signature_pointer_or_reference_decl (type, name)
tree type, name;
{
tree decl;
/* We don't enter this declaration in any sort of symbol table. */
decl = build_decl (TYPE_DECL, name, type);
TYPE_NAME (type) = decl;
TREE_CHAIN (type) = decl;
}
/* Construct, lay out and return the type of pointers or references
to signature TO_TYPE. If such a type has already been constructed,
reuse it. If CONSTP or VOLATILEP is specified, make the `optr' const
or volatile, respectively. If we are constructing a const/volatile
type variant and the main type variant doesn't exist yet, it is built
as well. If REFP is 1, we construct a signature reference, otherwise
a signature pointer is constructed.
This function is a subroutine of `build_signature_pointer_type' and
`build_signature_reference_type'. */
static tree
build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
tree to_type;
int constp, volatilep, refp;
{
register tree t, m;
register struct obstack *ambient_obstack = current_obstack;
register struct obstack *ambient_saveable_obstack = saveable_obstack;
m = refp ? SIGNATURE_REFERENCE_TO (to_type) : SIGNATURE_POINTER_TO (to_type);
/* If we don't have the main variant yet, construct it. */
if (m == NULL_TREE
&& (constp || volatilep))
m = build_signature_pointer_or_reference_type (to_type, 0, 0, refp);
/* Treat any nonzero argument as 1. */
constp = !!constp;
volatilep = !!volatilep;
refp = !!refp;
/* If not generating auxiliary info, search the chain of variants to see
if there is already one there just like the one we need to have. If so,
use that existing one.
We don't do this in the case where we are generating aux info because
in that case we want each typedef names to get it's own distinct type
node, even if the type of this new typedef is the same as some other
(existing) type. */
if (m && !flag_gen_aux_info)
for (t = m; t; t = TYPE_NEXT_VARIANT (t))
if (constp == TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t))))
&& volatilep == TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t)))))
return t;
/* We need a new one. If TO_TYPE is permanent, make this permanent too. */
if (TREE_PERMANENT (to_type))
{
current_obstack = &permanent_obstack;
saveable_obstack = &permanent_obstack;
}
/* A signature pointer or reference to a signature `s' looks like this:
struct {
void * optr;
const s * sptr;
vtbl_type_node * vptr;
};
A `const' signature pointer/reference is a
struct {
const void * optr;
const s * sptr;
vtbl_type_node * vptr;
};
Similarly, for `volatile' and `const volatile'.
*/
t = make_lang_type (RECORD_TYPE);
{
tree obj_type = build_type_variant (void_type_node, constp, volatilep);
tree optr_type = build_pointer_type (obj_type);
tree optr, sptr, vptr;
optr = build_lang_field_decl (FIELD_DECL,
get_identifier (SIGNATURE_OPTR_NAME),
optr_type);
DECL_FIELD_CONTEXT (optr) = t;
DECL_CLASS_CONTEXT (optr) = t;
if (m)
{
/* We can share `sptr' and `vptr' among type variants. */
sptr = TREE_CHAIN (TYPE_FIELDS (m));
vptr = TREE_CHAIN (sptr);
}
else
{
tree sig_tbl_type = build_type_variant (to_type, 1, 0);
sptr = build_lang_field_decl (FIELD_DECL,
get_identifier (SIGNATURE_SPTR_NAME),
build_pointer_type (sig_tbl_type));
vptr = build_lang_field_decl (FIELD_DECL,
get_identifier (SIGNATURE_VPTR_NAME),
build_pointer_type (vtbl_type_node));
DECL_FIELD_CONTEXT (sptr) = t;
DECL_CLASS_CONTEXT (sptr) = t;
DECL_FIELD_CONTEXT (vptr) = t;
DECL_CLASS_CONTEXT (vptr) = t;
TREE_CHAIN (sptr) = vptr;
TREE_CHAIN (vptr) = NULL_TREE;
}
TREE_CHAIN (optr) = sptr;
TYPE_FIELDS (t) = optr;
/* To make `build_vfn_ref' work when building a signature method call. */
CLASSTYPE_VFIELD (t) = vptr;
DECL_FCONTEXT (CLASSTYPE_VFIELD (t)) = t;
TYPE_ALIGN (t) = TYPE_ALIGN (optr_type);
}
{
tree name = build_signature_pointer_or_reference_name (to_type, constp,
volatilep, refp);
/* Build a DECL node for this type, so the debugger has access to it. */
build_signature_pointer_or_reference_decl (t, name);
}
CLASSTYPE_GOT_SEMICOLON (t) = 1;
IS_SIGNATURE_POINTER (t) = ! refp;
IS_SIGNATURE_REFERENCE (t) = refp;
SIGNATURE_TYPE (t) = to_type;
if (m)
{
/* Add this type to the chain of variants of TYPE.
Every type has to be its own TYPE_MAIN_VARIANT. */
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
TYPE_NEXT_VARIANT (m) = t;
}
else if (refp)
/* Record this type as the reference to TO_TYPE. */
SIGNATURE_REFERENCE_TO (to_type) = t;
else
/* Record this type as the pointer to TO_TYPE. */
SIGNATURE_POINTER_TO (to_type) = t;
/* Lay out the type. This function has many callers that are concerned
with expression-construction, and this simplifies them all.
Also, it guarantees the TYPE_SIZE is permanent if the type is. */
layout_type (t);
current_obstack = ambient_obstack;
saveable_obstack = ambient_saveable_obstack;
/* Ouput debug information for this type. */
rest_of_type_compilation (t, 1);
return t;
}
/* Construct, lay out and return the type of pointers to signature TO_TYPE. */
tree
build_signature_pointer_type (to_type, constp, volatilep)
tree to_type;
int constp, volatilep;
{
return
build_signature_pointer_or_reference_type (to_type, constp, volatilep, 0);
}
/* Construct, lay out and return the type of pointers to signature TO_TYPE. */
tree
build_signature_reference_type (to_type, constp, volatilep)
tree to_type;
int constp, volatilep;
{
return
build_signature_pointer_or_reference_type (to_type, constp, volatilep, 1);
}
/* Return the name of the signature table (as an IDENTIFIER_NODE)
for the given signature type SIG_TYPE and rhs type RHS_TYPE. */
static tree
get_sigtable_name (sig_type, rhs_type)
tree sig_type, rhs_type;
{
tree sig_type_id = build_typename_overload (sig_type);
tree rhs_type_id = build_typename_overload (rhs_type);
char *buf = (char *) alloca (sizeof (SIGTABLE_NAME_FORMAT_LONG)
+ IDENTIFIER_LENGTH (sig_type_id)
+ IDENTIFIER_LENGTH (rhs_type_id) + 20);
char *sig_ptr = IDENTIFIER_POINTER (sig_type_id);
char *rhs_ptr = IDENTIFIER_POINTER (rhs_type_id);
int i, j;
for (i = 0; sig_ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++)
/* do nothing */;
while (sig_ptr[i] >= '0' && sig_ptr[i] <= '9')
i += 1;
for (j = 0; rhs_ptr[j] == OPERATOR_TYPENAME_FORMAT[j]; j++)
/* do nothing */;
while (rhs_ptr[j] >= '0' && rhs_ptr[j] <= '9')
j += 1;
if (IS_SIGNATURE (rhs_type))
sprintf (buf, SIGTABLE_NAME_FORMAT_LONG, sig_ptr+i, rhs_ptr+j,
global_sigtable_name_counter++);
else
sprintf (buf, SIGTABLE_NAME_FORMAT, sig_ptr+i, rhs_ptr+j);
return get_identifier (buf);
}
/* Build a field decl that points to a signature member function. */
static tree
build_member_function_pointer (member)
tree member;
{
char *namstr = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (member));
int namlen = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (member));
char *name;
tree entry;
name = (char *) alloca (namlen + sizeof (SIGNATURE_FIELD_NAME) + 2);
sprintf (name, SIGNATURE_FIELD_NAME_FORMAT, namstr);
/* @@ Do we really want to xref signature table fields? */
GNU_xref_ref (current_function_decl, name);
entry = build_lang_field_decl (FIELD_DECL, get_identifier (name),
TYPE_MAIN_VARIANT (sigtable_entry_type));
TREE_CONSTANT (entry) = 1;
TREE_READONLY (entry) = 1;
/* @@ Do we really want to xref signature table fields? */
GNU_xref_decl (current_function_decl, entry);
return entry;
}
/* For each FUNCTION_DECL in a signature we construct a member function
pointer of the appropriate type. We also need two flags to test
whether the member function pointer points to a virtual function or
to a default implementation. Those flags will be the two lower order
bits of the member function pointer (or the two higher order bits,
based on the configuration).
The new FIELD_DECLs are appended at the end of the last (and only)
sublist of `list_of_fieldlists.'
As a side effect, each member function in the signature gets the
`decl.ignored' bit turned on, so we don't output debug info for it. */
void
append_signature_fields (list_of_fieldlists)
tree list_of_fieldlists;
{
tree l, x;
tree last_x = NULL_TREE;
tree mfptr;
tree last_mfptr;
tree mfptr_list = NULL_TREE;
/* For signatures it should actually be only a list with one element. */
for (l = list_of_fieldlists; l; l = TREE_CHAIN (l))
{
for (x = TREE_VALUE (l); x; x = TREE_CHAIN (x))
{
if (TREE_CODE (x) == FUNCTION_DECL)
{
mfptr = build_member_function_pointer (x);
DECL_MEMFUNC_POINTER_TO (x) = mfptr;
DECL_MEMFUNC_POINTING_TO (mfptr) = x;
DECL_IGNORED_P (x) = 1;
DECL_IN_AGGR_P (mfptr) = 1;
if (! mfptr_list)
mfptr_list = last_mfptr = mfptr;
else
{
TREE_CHAIN (last_mfptr) = mfptr;
last_mfptr = mfptr;
}
}
last_x = x;
}
}
/* Append the lists. */
if (last_x && mfptr_list)
{
TREE_CHAIN (last_x) = mfptr_list;
TREE_CHAIN (last_mfptr) = NULL_TREE;
}
}
/* Compare the types of a signature member function and a class member
function. Returns 1 if the types are in the C++ `<=' relationship.
If we have a signature pointer/reference as argument or return type
we don't want to do a recursive conformance check. The conformance
check only succeeds if both LHS and RHS refer to the same signature
pointer. Otherwise we need to keep information about parameter types
around at run time to initialize the signature table correctly. */
static int
match_method_types (sig_mtype, class_mtype)
tree sig_mtype, class_mtype;
{
tree sig_return_type = TREE_TYPE (sig_mtype);
tree sig_arg_types = TYPE_ARG_TYPES (sig_mtype);
tree class_return_type = TREE_TYPE (class_mtype);
tree class_arg_types = TYPE_ARG_TYPES (class_mtype);
/* The return types have to be the same. */
if (! comptypes (sig_return_type, class_return_type, 1))
return 0;
/* Compare the first argument `this.' */
{
/* Get the type of what the `optr' is pointing to. */
tree sig_this =
TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types))));
tree class_this = TREE_VALUE (class_arg_types);
if (TREE_CODE (class_this) == RECORD_TYPE) /* Is `this' a sig ptr? */
class_this = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (class_this)));
else
class_this = TREE_TYPE (class_this);
/* If a signature method's `this' is const or volatile, so has to be
the corresponding class method's `this.' */
if ((TYPE_READONLY (sig_this) && ! TYPE_READONLY (class_this))
|| (TYPE_VOLATILE (sig_this) && ! TYPE_VOLATILE (class_this)))
return 0;
}
sig_arg_types = TREE_CHAIN (sig_arg_types);
class_arg_types = TREE_CHAIN (class_arg_types);
/* The number of arguments and the argument types have to be the same. */
return compparms (sig_arg_types, class_arg_types, 3);
}
/* Undo casts of opaque type variables to the RHS types. */
static void
undo_casts (sig_ty)
tree sig_ty;
{
tree field = TYPE_FIELDS (sig_ty);
/* Since all the FIELD_DECLs for the signature table entries are at the end
of the chain (see `append_signature_fields'), we can do it this way. */
for (; field && TREE_CODE (field) != FIELD_DECL; field = TREE_CHAIN (field))
if (TYPE_MAIN_VARIANT (TREE_TYPE (field)) == opaque_type_node)
TREE_TYPE (TREE_TYPE (field)) = TREE_TYPE (ptr_type_node);
}
/* Do the type checking necessary to see whether the `rhs' conforms to
the lhs's `sig_ty'. Depending on the type of `rhs' return a NULL_TREE,
an integer_zero_node, a constructor, or an expression offsetting the
`rhs' signature table. */
static tree
build_signature_table_constructor (sig_ty, rhs)
tree sig_ty, rhs;
{
tree rhstype = TREE_TYPE (rhs);
tree sig_field = TYPE_FIELDS (sig_ty);
tree result = NULL_TREE;
tree first_rhs_field = NULL_TREE;
tree last_rhs_field;
int sig_ptr_p = IS_SIGNATURE (rhstype);
int offset_p = sig_ptr_p;
rhstype = sig_ptr_p ? rhstype : TREE_TYPE (rhstype);
if (CLASSTYPE_TAGS (sig_ty))
{
sorry ("conformance check with signature containing class declarations");
return error_mark_node;
}
for (; sig_field; sig_field = TREE_CHAIN (sig_field))
{
tree basetype_path, baselink, basetypes;
tree sig_method, sig_mname, sig_mtype;
tree rhs_method, tbl_entry;
if (TREE_CODE (sig_field) == TYPE_DECL)
{
tree sig_field_type = TREE_TYPE (sig_field);
if (TYPE_MAIN_VARIANT (sig_field_type) == opaque_type_node)
{
/* We've got an opaque type here. */
tree oty_name = DECL_NAME (sig_field);
tree oty_type = lookup_field (rhstype, oty_name, 1, 1);
if (oty_type == NULL_TREE || oty_type == error_mark_node)
{
cp_error ("class `%T' does not contain type `%T'",
rhstype, oty_type);
undo_casts (sig_ty);
return error_mark_node;
}
oty_type = TREE_TYPE (oty_type);
/* Cast `sig_field' to be of type `oty_type'. This will be
undone in `undo_casts' by walking over all the TYPE_DECLs. */
TREE_TYPE (sig_field_type) = TREE_TYPE (oty_type);
}
/* If we don't have an opaque type, we can ignore the `typedef'. */
continue;
}
/* Find the signature method corresponding to `sig_field'. */
sig_method = DECL_MEMFUNC_POINTING_TO (sig_field);
sig_mname = DECL_NAME (sig_method);
sig_mtype = TREE_TYPE (sig_method);
basetype_path = TYPE_BINFO (rhstype);
baselink = lookup_fnfields (basetype_path, sig_mname, 0);
if (baselink == NULL_TREE || baselink == error_mark_node)
{
if (! IS_DEFAULT_IMPLEMENTATION (sig_method))
{
cp_error ("class `%T' does not contain method `%s'",
rhstype, (int) IDENTIFIER_POINTER (sig_mname));
undo_casts (sig_ty);
return error_mark_node;
}
else
{
/* We use the signature's default implementation. */
rhs_method = sig_method;
}
}
else
{
/* Find the class method of the correct type. */
basetypes = TREE_PURPOSE (baselink);
if (TREE_CODE (basetypes) == TREE_LIST)
basetypes = TREE_VALUE (basetypes);
rhs_method = TREE_VALUE (baselink);
for (; rhs_method; rhs_method = TREE_CHAIN (rhs_method))
if (sig_mname == DECL_NAME (rhs_method)
&& ! DECL_STATIC_FUNCTION_P (rhs_method)
&& match_method_types (sig_mtype, TREE_TYPE (rhs_method)))
break;
if (rhs_method == NULL_TREE
|| (compute_access (basetypes, rhs_method)
!= access_public))
{
error ("class `%s' does not contain a method conforming to `%s'",
TYPE_NAME_STRING (rhstype),
fndecl_as_string (NULL, sig_method, 1));
undo_casts (sig_ty);
return error_mark_node;
}
}
if (sig_ptr_p && rhs_method != sig_method)
{
tree rhs_field = DECL_MEMFUNC_POINTER_TO (rhs_method);
if (first_rhs_field == NULL_TREE)
{
first_rhs_field = rhs_field;
last_rhs_field = rhs_field;
}
else if (TREE_CHAIN (last_rhs_field) == rhs_field)
last_rhs_field = rhs_field;
else
offset_p = 0;
tbl_entry = build_component_ref (rhs, DECL_NAME (rhs_field),
NULL_TREE, 1);
}
else
{
tree code, offset, pfn;
if (rhs_method == sig_method)
{
code = integer_two_node;
offset = integer_zero_node;
pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
TREE_TYPE (pfn) = ptr_type_node;
offset_p = 0; /* we can't offset the rhs sig table */
}
else if (DECL_VINDEX (rhs_method))
{
code = integer_one_node;
offset = DECL_VINDEX (rhs_method);
pfn = null_pointer_node;
}
else
{
code = integer_zero_node;
offset = integer_zero_node;
pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
TREE_TYPE (pfn) = ptr_type_node;
}
tbl_entry = tree_cons (NULL_TREE, code,
tree_cons (NULL_TREE, offset,
build_tree_list (NULL_TREE, pfn)));
tbl_entry = build_nt (CONSTRUCTOR, NULL_TREE, tbl_entry);
TREE_HAS_CONSTRUCTOR (tbl_entry) = 1;
TREE_CONSTANT (tbl_entry) = 1;
}
/* Chain those function address expressions together. */
if (result)
result = tree_cons (NULL_TREE, tbl_entry, result);
else
result = build_tree_list (NULL_TREE, tbl_entry);
}
if (result == NULL_TREE)
{
undo_casts (sig_ty);
return NULL_TREE;
}
if (offset_p)
{
if (first_rhs_field == TYPE_FIELDS (rhstype))
{
undo_casts (sig_ty);
return integer_zero_node;
}
else
{
undo_casts (sig_ty);
return build_component_ref (rhs, DECL_NAME (first_rhs_field),
NULL_TREE, 0);
}
}
result = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (result));
TREE_HAS_CONSTRUCTOR (result) = 1;
TREE_CONSTANT (result) = !sig_ptr_p;
undo_casts (sig_ty);
return result;
}
/* Build a signature table declaration and initialize it or return an
existing one if we built one already. If we don't get a constructor
as initialization expression, we don't need a new signature table
variable and just hand back the init expression.
The declaration processing is done by hand instead of using `finish_decl'
so that we can make signature pointers global variables instead of
static ones. */
static tree
build_sigtable (sig_type, rhs_type, init_from)
tree sig_type, rhs_type, init_from;
{
tree name = NULL_TREE;
tree decl = NULL_TREE;
tree init_expr;
push_obstacks_nochange ();
end_temporary_allocation ();
if (! IS_SIGNATURE (rhs_type))
{
name = get_sigtable_name (sig_type, rhs_type);
decl = IDENTIFIER_GLOBAL_VALUE (name);
}
if (decl == NULL_TREE)
{
tree init;
/* We allow only one signature table to be generated for signatures
with opaque types. Otherwise we create a loophole in the type
system since we could cast data from one classes implementation
of the opaque type to that of another class. */
if (SIGNATURE_HAS_OPAQUE_TYPEDECLS (sig_type)
&& SIGTABLE_HAS_BEEN_GENERATED (sig_type))
{
error ("signature with opaque type implemented by multiple classes");
return error_mark_node;
}
SIGTABLE_HAS_BEEN_GENERATED (sig_type) = 1;
init_expr = build_signature_table_constructor (sig_type, init_from);
if (TREE_CODE (init_expr) != CONSTRUCTOR)
return init_expr;
if (name == NULL_TREE)
name = get_sigtable_name (sig_type, rhs_type);
{
tree context = current_function_decl;
/* Make the signature table global, not just static in whichever
function a signature pointer/ref is used for the first time. */
current_function_decl = NULL_TREE;
decl = pushdecl_top_level (build_decl (VAR_DECL, name, sig_type));
current_function_decl = context;
}
IDENTIFIER_GLOBAL_VALUE (name) = decl;
store_init_value (decl, init_expr);
if (IS_SIGNATURE (rhs_type))
{
init = DECL_INITIAL (decl);
DECL_INITIAL (decl) = error_mark_node;
}
DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (decl));
#if 0
/* GDB-4.7 doesn't find the initialization value of a signature table
when it is constant. */
TREE_READONLY (decl) = 1;
#endif
TREE_STATIC (decl) = 1;
TREE_USED (decl) = 1;
make_decl_rtl (decl, NULL, 1);
if (IS_SIGNATURE (rhs_type))
expand_static_init (decl, init);
}
pop_obstacks ();
return decl;
}
/* Create a constructor or modify expression if the LHS of an assignment
is a signature pointer or a signature reference. If LHS is a record
type node, we build a constructor, otherwise a compound expression. */
tree
build_signature_pointer_constructor (lhs, rhs)
tree lhs, rhs;
{
register struct obstack *ambient_obstack = current_obstack;
register struct obstack *ambient_saveable_obstack = saveable_obstack;
int initp = (TREE_CODE (lhs) == RECORD_TYPE);
tree lhstype = initp ? lhs : TREE_TYPE (lhs);
tree rhstype = TREE_TYPE (rhs);
tree sig_ty = SIGNATURE_TYPE (lhstype);
tree sig_tbl, sptr_expr, optr_expr, vptr_expr;
tree result;
if (! ((TREE_CODE (rhstype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (rhstype)) == RECORD_TYPE)
|| (TYPE_LANG_SPECIFIC (rhstype) &&
(IS_SIGNATURE_POINTER (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype)))))
{
error ("invalid assignment to signature pointer or reference");
return error_mark_node;
}
/* If SIG_TY is permanent, make the signature table constructor and
the signature pointer/reference constructor permanent too. */
if (TREE_PERMANENT (sig_ty))
{
current_obstack = &permanent_obstack;
saveable_obstack = &permanent_obstack;
}
if (TYPE_LANG_SPECIFIC (rhstype) &&
(IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype)))
{
if (SIGNATURE_TYPE (rhstype) == sig_ty)
{
/* LHS and RHS are signature pointers/refs of the same signature. */
optr_expr = build_optr_ref (rhs);
sptr_expr = build_sptr_ref (rhs);
vptr_expr = build_vptr_ref (rhs);
}
else
{
/* We need to create a new signature table and copy
elements from the rhs signature table. */
tree rhs_sptr_ref = build_sptr_ref (rhs);
tree rhs_tbl = build1 (INDIRECT_REF, SIGNATURE_TYPE (rhstype),
rhs_sptr_ref);
sig_tbl = build_sigtable (sig_ty, SIGNATURE_TYPE (rhstype), rhs_tbl);
if (sig_tbl == error_mark_node)
return error_mark_node;
optr_expr = build_optr_ref (rhs);
if (sig_tbl == integer_zero_node)
sptr_expr = rhs_sptr_ref;
else
sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0);
TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty);
vptr_expr = build_vptr_ref (rhs);
}
}
else
{
tree rhs_vptr;
if (TYPE_USES_COMPLEX_INHERITANCE (TREE_TYPE (rhstype)))
{
sorry ("class with multiple inheritance as implementation of signature");
return error_mark_node;
}
sig_tbl = build_sigtable (sig_ty, TREE_TYPE (rhstype), rhs);
if (sig_tbl == error_mark_node)
return error_mark_node;
optr_expr = rhs;
sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0);
if (CLASSTYPE_VFIELD (TREE_TYPE (rhstype)))
{
rhs_vptr = DECL_NAME (CLASSTYPE_VFIELD (TREE_TYPE (rhstype)));
vptr_expr = build_component_ref (build_indirect_ref (rhs, 0),
rhs_vptr, NULL_TREE, 0);
}
else
vptr_expr = null_pointer_node;
TREE_TYPE (vptr_expr) = build_pointer_type (vtbl_type_node);
}
if (initp)
{
result = tree_cons (NULL_TREE, optr_expr,
tree_cons (NULL_TREE, sptr_expr,
build_tree_list (NULL_TREE, vptr_expr)));
result = build_nt (CONSTRUCTOR, NULL_TREE, result);
TREE_HAS_CONSTRUCTOR (result) = 1;
result = digest_init (lhstype, result, 0);
}
else
{
if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype))
readonly_error (lhs, "assignment", 0);
optr_expr = build_modify_expr (build_optr_ref (lhs), NOP_EXPR,
optr_expr);
sptr_expr = build_modify_expr (build_sptr_ref (lhs), NOP_EXPR,
sptr_expr);
vptr_expr = build_modify_expr (build_vptr_ref (lhs), NOP_EXPR,
vptr_expr);
result = tree_cons (NULL_TREE, optr_expr,
tree_cons (NULL_TREE, sptr_expr,
tree_cons (NULL_TREE, vptr_expr,
build_tree_list (NULL_TREE,
lhs))));
result = build_compound_expr (result);
}
current_obstack = ambient_obstack;
saveable_obstack = ambient_saveable_obstack;
return result;
}
/* Build a temporary variable declaration for the instance of a signature
member function call if it isn't a declaration node already. Simply
using a SAVE_EXPR doesn't work since we need `this' in both branches
of a conditional expression. */
static tree
save_this (instance)
tree instance;
{
tree decl;
if (TREE_CODE_CLASS (TREE_CODE (instance)) == 'd')
decl = instance;
else
{
decl = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (instance));
DECL_REGISTER (decl) = 1;
layout_decl (decl, 0);
expand_decl (decl);
}
return decl;
}
/* Build a signature member function call. Looks up the signature table
entry corresponding to FUNCTION. Depending on the value of the CODE
field, either call the function in PFN directly, or use OFFSET to
index INSTANCE's virtual function table. */
tree
build_signature_method_call (basetype, instance, function, parms)
tree basetype, instance, function, parms;
{
tree saved_instance = save_this (instance); /* Create temp for `this'. */
tree signature_tbl_ptr = build_sptr_ref (saved_instance);
tree sig_field_name = DECL_NAME (DECL_MEMFUNC_POINTER_TO (function));
tree basetype_path = TYPE_BINFO (basetype);
tree tbl_entry = build_component_ref (build1 (INDIRECT_REF, basetype,
signature_tbl_ptr),
sig_field_name, basetype_path, 1);
tree code, offset, pfn, vfn;
tree deflt_call = NULL_TREE, direct_call, virtual_call, result;
code = build_component_ref (tbl_entry, get_identifier (SIGTABLE_CODE_NAME),
NULL_TREE, 1);
offset = build_component_ref (tbl_entry,
get_identifier (SIGTABLE_OFFSET_NAME),
NULL_TREE, 1);
pfn = build_component_ref (tbl_entry, get_identifier (SIGTABLE_PFN_NAME),
NULL_TREE, 1);
TREE_TYPE (pfn) = build_pointer_type (TREE_TYPE (function));
if (IS_DEFAULT_IMPLEMENTATION (function))
{
pfn = save_expr (pfn);
deflt_call = build_function_call (pfn,
tree_cons (NULL_TREE, saved_instance,
TREE_CHAIN (parms)));
}
{
/* Cast the signature method to have `this' of a normal pointer type. */
tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))));
TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) =
build_type_variant (TYPE_POINTER_TO (basetype),
TYPE_READONLY (old_this),
TYPE_VOLATILE (old_this));
direct_call = build_function_call (pfn, parms);
vfn = build_vfn_ref (&TREE_VALUE (parms), saved_instance, offset);
TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function));
virtual_call = build_function_call (vfn, parms);
/* Undo the cast, make `this' a signature pointer again. */
TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = old_this;
}
/* Once the function was found, there should be no reason why we
couldn't build the member function pointer call. */
if (!direct_call || direct_call == error_mark_node
|| !virtual_call || virtual_call == error_mark_node
|| (IS_DEFAULT_IMPLEMENTATION (function)
&& (!deflt_call || deflt_call == error_mark_node)))
{
compiler_error ("cannot build call of signature member function `%s'",
fndecl_as_string (NULL, function, 1));
return error_mark_node;
}
if (IS_DEFAULT_IMPLEMENTATION (function))
{
tree test = build_binary_op_nodefault (EQ_EXPR, code, integer_one_node,
EQ_EXPR);
result = build_conditional_expr (code,
build_conditional_expr (test,
virtual_call,
deflt_call),
direct_call);
}
else
result = build_conditional_expr (code, virtual_call, direct_call);
/* If we created a temporary variable for `this', initialize it first. */
if (instance != saved_instance)
result = build (COMPOUND_EXPR, TREE_TYPE (result),
build_modify_expr (saved_instance, NOP_EXPR, instance),
result);
return result;
}
/* Create a COMPONENT_REF expression for referencing the OPTR field
of a signature pointer or reference. */
tree
build_optr_ref (instance)
tree instance;
{
tree field = get_identifier (SIGNATURE_OPTR_NAME);
return build_component_ref (instance, field, NULL_TREE, 1);
}
/* Create a COMPONENT_REF expression for referencing the SPTR field
of a signature pointer or reference. */
tree
build_sptr_ref (instance)
tree instance;
{
tree field = get_identifier (SIGNATURE_SPTR_NAME);
return build_component_ref (instance, field, NULL_TREE, 1);
}
/* Create a COMPONENT_REF expression for referencing the VPTR field
of a signature pointer or reference. */
tree
build_vptr_ref (instance)
tree instance;
{
tree field = get_identifier (SIGNATURE_VPTR_NAME);
return build_component_ref (instance, field, NULL_TREE, 1);
}

1141
gcc/cp/spew.c Normal file

File diff suppressed because it is too large Load Diff

1797
gcc/cp/tree.c Normal file

File diff suppressed because it is too large Load Diff

6926
gcc/cp/typeck.c Normal file

File diff suppressed because it is too large Load Diff

1827
gcc/cp/typeck2.c Normal file

File diff suppressed because it is too large Load Diff

827
gcc/cp/xref.c Normal file
View File

@ -0,0 +1,827 @@
/* Code for handling XREF output from GNU C++.
Copyright (C) 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "tree.h"
#include <stdio.h>
#include "cp-tree.h"
#include "input.h"
#include <ctype.h>
extern char *getpwd ();
extern char *index ();
extern char *rindex ();
/* The character(s) used to join a directory specification (obtained with
getwd or equivalent) with a non-absolute file name. */
#ifndef FILE_NAME_JOINER
#define FILE_NAME_JOINER "/"
#endif
/* Nonzero if NAME as a file name is absolute. */
#ifndef FILE_NAME_ABSOLUTE_P
#define FILE_NAME_ABSOLUTE_P(NAME) (NAME[0] == '/')
#endif
/* For cross referencing. */
int flag_gnu_xref;
/************************************************************************/
/* */
/* Common definitions */
/* */
/************************************************************************/
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0
#endif
#define PALLOC(typ) ((typ *) calloc(1,sizeof(typ)))
/* Return a malloc'd copy of STR. */
#define SALLOC(str) \
((char *) ((str) == NULL ? NULL \
: (char *) strcpy ((char *) malloc (strlen ((str)) + 1), (str))))
#define SFREE(str) (str != NULL && (free(str),0))
#define STREQL(s1,s2) (strcmp((s1),(s2)) == 0)
#define STRNEQ(s1,s2) (strcmp((s1),(s2)) != 0)
#define STRLSS(s1,s2) (strcmp((s1),(s2)) < 0)
#define STRLEQ(s1,s2) (strcmp((s1),(s2)) <= 0)
#define STRGTR(s1,s2) (strcmp((s1),(s2)) > 0)
#define STRGEQ(s1,s2) (strcmp((s1),(s2)) >= 0)
/************************************************************************/
/* */
/* Type definitions */
/* */
/************************************************************************/
typedef struct _XREF_FILE * XREF_FILE;
typedef struct _XREF_SCOPE * XREF_SCOPE;
typedef struct _XREF_FILE
{
char *name;
char *outname;
XREF_FILE next;
} XREF_FILE_INFO;
typedef struct _XREF_SCOPE
{
int gid;
int lid;
XREF_FILE file;
int start;
XREF_SCOPE outer;
} XREF_SCOPE_INFO;
/************************************************************************/
/* */
/* Local storage */
/* */
/************************************************************************/
static char doing_xref = 0;
static FILE * xref_file = NULL;
static char xref_name[1024];
static XREF_FILE all_files = NULL;
static char * wd_name = NULL;
static XREF_SCOPE cur_scope = NULL;
static int scope_ctr = 0;
static XREF_FILE last_file = NULL;
static tree last_fndecl = NULL;
/************************************************************************/
/* */
/* Forward definitions */
/* */
/************************************************************************/
extern void GNU_xref_begin();
extern void GNU_xref_end();
extern void GNU_xref_file();
extern void GNU_xref_start_scope();
extern void GNU_xref_end_scope();
extern void GNU_xref_ref();
extern void GNU_xref_decl();
extern void GNU_xref_call();
extern void GNU_xref_function();
extern void GNU_xref_assign();
extern void GNU_xref_hier();
extern void GNU_xref_member();
static void gen_assign();
static XREF_FILE find_file();
static char * filename();
static char * fctname();
static char * declname();
static void simplify_type();
static char * fixname();
static void open_xref_file();
extern char * type_as_string();
/* Start cross referencing. FILE is the name of the file we xref. */
void
GNU_xref_begin (file)
char *file;
{
doing_xref = 1;
if (file != NULL && STRNEQ (file,"-"))
{
open_xref_file(file);
GNU_xref_file(file);
}
}
/* Finish cross-referencing. ERRCNT is the number of errors
we encountered. */
void
GNU_xref_end (ect)
int ect;
{
XREF_FILE xf;
if (!doing_xref) return;
xf = find_file (input_filename);
if (xf == NULL) return;
while (cur_scope != NULL)
GNU_xref_end_scope(cur_scope->gid,0,0,0,0);
doing_xref = 0;
if (xref_file == NULL) return;
fclose (xref_file);
xref_file = NULL;
all_files = NULL;
if (ect > 0) unlink (xref_name);
}
/* Write out xref for file named NAME. */
void
GNU_xref_file (name)
char *name;
{
XREF_FILE xf;
if (!doing_xref || name == NULL) return;
if (xref_file == NULL)
{
open_xref_file (name);
if (!doing_xref) return;
}
if (all_files == NULL)
fprintf(xref_file,"SCP * 0 0 0 0 RESET\n");
xf = find_file (name);
if (xf != NULL) return;
xf = PALLOC (XREF_FILE_INFO);
xf->name = SALLOC (name);
xf->next = all_files;
all_files = xf;
if (wd_name == NULL)
wd_name = getpwd ();
if (FILE_NAME_ABSOLUTE_P (name) || ! wd_name)
xf->outname = xf->name;
else
{
char *nmbuf
= (char *) malloc (strlen (wd_name) + strlen (FILE_NAME_JOINER)
+ strlen (name) + 1);
sprintf (nmbuf, "%s%s%s", wd_name, FILE_NAME_JOINER, name);
name = nmbuf;
xf->outname = nmbuf;
}
fprintf (xref_file, "FIL %s %s 0\n", name, wd_name);
filename (xf);
fctname (NULL);
}
/* Start a scope identified at level ID. */
void
GNU_xref_start_scope (id)
HOST_WIDE_INT id;
{
XREF_SCOPE xs;
XREF_FILE xf;
if (!doing_xref) return;
xf = find_file (input_filename);
xs = PALLOC (XREF_SCOPE_INFO);
xs->file = xf;
xs->start = lineno;
if (xs->start <= 0) xs->start = 1;
xs->gid = id;
xs->lid = ++scope_ctr;
xs->outer = cur_scope;
cur_scope = xs;
}
/* Finish a scope at level ID.
INID is ???
PRM is ???
KEEP is nonzero iff this scope is retained (nonzero if it's
a compiler-generated invisible scope).
TRNS is ??? */
void
GNU_xref_end_scope (id,inid,prm,keep,trns)
HOST_WIDE_INT id;
HOST_WIDE_INT inid;
int prm,keep,trns;
{
XREF_FILE xf;
XREF_SCOPE xs,lxs,oxs;
char *stype;
if (!doing_xref) return;
xf = find_file (input_filename);
if (xf == NULL) return;
lxs = NULL;
for (xs = cur_scope; xs != NULL; xs = xs->outer)
{
if (xs->gid == id) break;
lxs = xs;
}
if (xs == NULL) return;
if (inid != 0) {
for (oxs = cur_scope; oxs != NULL; oxs = oxs->outer) {
if (oxs->gid == inid) break;
}
if (oxs == NULL) return;
inid = oxs->lid;
}
if (prm == 2) stype = "SUE";
else if (prm != 0) stype = "ARGS";
else if (keep == 2 || inid != 0) stype = "INTERN";
else stype = "EXTERN";
fprintf (xref_file,"SCP %s %d %d %d %d %s\n",
filename (xf), xs->start, lineno,xs->lid, inid, stype);
if (lxs == NULL) cur_scope = xs->outer;
else lxs->outer = xs->outer;
free (xs);
}
/* Output a reference to NAME in FNDECL. */
void
GNU_xref_ref (fndecl,name)
tree fndecl;
char *name;
{
XREF_FILE xf;
if (!doing_xref) return;
xf = find_file (input_filename);
if (xf == NULL) return;
fprintf (xref_file, "REF %s %d %s %s\n",
filename (xf), lineno, fctname (fndecl), name);
}
/* Output a reference to DECL in FNDECL. */
void
GNU_xref_decl (fndecl,decl)
tree fndecl;
tree decl;
{
XREF_FILE xf,xf1;
char *cls;
char *name;
char buf[10240];
int uselin;
if (!doing_xref) return;
xf = find_file (input_filename);
if (xf == NULL) return;
uselin = FALSE;
if (TREE_CODE (decl) == TYPE_DECL) cls = "TYPEDEF";
else if (TREE_CODE (decl) == FIELD_DECL) cls = "FIELD";
else if (TREE_CODE (decl) == VAR_DECL)
{
if (fndecl == NULL && TREE_STATIC(decl)
&& TREE_READONLY(decl) && DECL_INITIAL(decl) != 0
&& !TREE_PUBLIC(decl) && !DECL_EXTERNAL(decl)
&& DECL_MODE(decl) != BLKmode) cls = "CONST";
else if (DECL_EXTERNAL(decl)) cls = "EXTERN";
else if (TREE_PUBLIC(decl)) cls = "EXTDEF";
else if (TREE_STATIC(decl)) cls = "STATIC";
else if (DECL_REGISTER(decl)) cls = "REGISTER";
else cls = "AUTO";
}
else if (TREE_CODE (decl) == PARM_DECL) cls = "PARAM";
else if (TREE_CODE (decl) == FIELD_DECL) cls = "FIELD";
else if (TREE_CODE (decl) == CONST_DECL) cls = "CONST";
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
if (DECL_EXTERNAL (decl)) cls = "EXTERN";
else if (TREE_PUBLIC (decl)) cls = "EFUNCTION";
else cls = "SFUNCTION";
}
else if (TREE_CODE (decl) == LABEL_DECL) cls = "LABEL";
else if (TREE_CODE (decl) == UNION_TYPE)
{
cls = "UNIONID";
decl = TYPE_NAME (decl);
uselin = TRUE;
}
else if (TREE_CODE (decl) == RECORD_TYPE)
{
if (CLASSTYPE_DECLARED_CLASS (decl)) cls = "CLASSID";
else if (IS_SIGNATURE (decl)) cls = "SIGNATUREID";
else cls = "STRUCTID";
decl = TYPE_NAME (decl);
uselin = TRUE;
}
else if (TREE_CODE (decl) == ENUMERAL_TYPE)
{
cls = "ENUMID";
decl = TYPE_NAME (decl);
uselin = TRUE;
}
else cls = "UNKNOWN";
if (decl == NULL || DECL_NAME (decl) == NULL) return;
if (uselin && decl->decl.linenum > 0 && decl->decl.filename != NULL)
{
xf1 = find_file (decl->decl.filename);
if (xf1 != NULL)
{
lineno = decl->decl.linenum;
xf = xf1;
}
}
if (DECL_ASSEMBLER_NAME (decl))
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
else
name = IDENTIFIER_POINTER (DECL_NAME (decl));
strcpy (buf, type_as_string (TREE_TYPE (decl), 0));
simplify_type (buf);
fprintf (xref_file, "DCL %s %d %s %d %s %s %s\n",
filename(xf), lineno, name,
(cur_scope != NULL ? cur_scope->lid : 0),
cls, fctname(fndecl), buf);
if (STREQL (cls, "STRUCTID") || STREQL (cls, "UNIONID")
|| STREQL (cls, "SIGNATUREID"))
{
cls = "CLASSID";
fprintf (xref_file, "DCL %s %d %s %d %s %s %s\n",
filename(xf), lineno,name,
(cur_scope != NULL ? cur_scope->lid : 0),
cls, fctname(fndecl), buf);
}
}
/* Output a reference to a call to NAME in FNDECL. */
void
GNU_xref_call (fndecl, name)
tree fndecl;
char *name;
{
XREF_FILE xf;
char buf[1024];
char *s;
if (!doing_xref) return;
xf = find_file (input_filename);
if (xf == NULL) return;
name = fixname (name, buf);
for (s = name; *s != 0; ++s)
if (*s == '_' && s[1] == '_') break;
if (*s != 0) GNU_xref_ref (fndecl, name);
fprintf (xref_file, "CAL %s %d %s %s\n",
filename (xf), lineno, name, fctname (fndecl));
}
/* Output cross-reference info about FNDECL. If non-NULL,
ARGS are the arguments for the function (i.e., before the FUNCTION_DECL
has been fully built). */
void
GNU_xref_function (fndecl, args)
tree fndecl;
tree args;
{
XREF_FILE xf;
int ct;
char buf[1024];
if (!doing_xref) return;
xf = find_file (input_filename);
if (xf == NULL) return;
ct = 0;
buf[0] = 0;
if (args == NULL) args = DECL_ARGUMENTS (fndecl);
GNU_xref_decl (NULL, fndecl);
for ( ; args != NULL; args = TREE_CHAIN (args))
{
GNU_xref_decl (fndecl,args);
if (ct != 0) strcat (buf,",");
strcat (buf, declname (args));
++ct;
}
fprintf (xref_file, "PRC %s %d %s %d %d %s\n",
filename(xf), lineno, declname(fndecl),
(cur_scope != NULL ? cur_scope->lid : 0),
ct, buf);
}
/* Output cross-reference info about an assignment to NAME. */
void
GNU_xref_assign(name)
tree name;
{
XREF_FILE xf;
if (!doing_xref) return;
xf = find_file(input_filename);
if (xf == NULL) return;
gen_assign(xf, name);
}
static void
gen_assign(xf, name)
XREF_FILE xf;
tree name;
{
char *s;
s = NULL;
switch (TREE_CODE (name))
{
case IDENTIFIER_NODE :
s = IDENTIFIER_POINTER(name);
break;
case VAR_DECL :
s = declname(name);
break;
case COMPONENT_REF :
gen_assign(xf, TREE_OPERAND(name, 0));
gen_assign(xf, TREE_OPERAND(name, 1));
break;
case INDIRECT_REF :
case OFFSET_REF :
case ARRAY_REF :
case BUFFER_REF :
gen_assign(xf, TREE_OPERAND(name, 0));
break;
case COMPOUND_EXPR :
gen_assign(xf, TREE_OPERAND(name, 1));
break;
default :
break;
}
if (s != NULL)
fprintf(xref_file, "ASG %s %d %s\n", filename(xf), lineno, s);
}
/* Output cross-reference info about a class hierarchy.
CLS is the class type of interest. BASE is a baseclass
for CLS. PUB and VIRT give the access info about
the class derivation. FRND is nonzero iff BASE is a friend
of CLS.
??? Needs to handle nested classes. */
void
GNU_xref_hier(cls, base, pub, virt, frnd)
char *cls;
char *base;
int pub;
int virt;
int frnd;
{
XREF_FILE xf;
if (!doing_xref) return;
xf = find_file(input_filename);
if (xf == NULL) return;
fprintf(xref_file, "HIE %s %d %s %s %d %d %d\n",
filename(xf), lineno, cls, base, pub, virt, frnd);
}
/* Output cross-reference info about class members. CLS
is the containing type; FLD is the class member. */
void
GNU_xref_member(cls, fld)
tree cls;
tree fld;
{
XREF_FILE xf;
char *prot;
int confg, pure;
char *d;
int i;
char buf[1024], bufa[1024];
if (!doing_xref) return;
xf = find_file(fld->decl.filename);
if (xf == NULL) return;
if (TREE_PRIVATE (fld)) prot = "PRIVATE";
else if (TREE_PROTECTED(fld)) prot = "PROTECTED";
else prot = "PUBLIC";
confg = 0;
if (TREE_CODE (fld) == FUNCTION_DECL && DECL_CONST_MEMFUNC_P(fld))
confg = 1;
else if (TREE_CODE (fld) == CONST_DECL)
confg = 1;
pure = 0;
if (TREE_CODE (fld) == FUNCTION_DECL && DECL_ABSTRACT_VIRTUAL_P(fld))
pure = 1;
d = IDENTIFIER_POINTER(cls);
sprintf(buf, "%d%s", strlen(d), d);
i = strlen(buf);
strcpy(bufa, declname(fld));
#ifdef XREF_SHORT_MEMBER_NAMES
for (p = &bufa[1]; *p != 0; ++p)
{
if (p[0] == '_' && p[1] == '_' && p[2] >= '0' && p[2] <= '9') {
if (strncmp(&p[2], buf, i) == 0) *p = 0;
break;
}
else if (p[0] == '_' && p[1] == '_' && p[2] == 'C' && p[3] >= '0' && p[3] <= '9') {
if (strncmp(&p[3], buf, i) == 0) *p = 0;
break;
}
}
#endif
fprintf(xref_file, "MEM %s %d %s %s %s %d %d %d %d %d %d %d\n",
filename(xf), fld->decl.linenum, d, bufa, prot,
(TREE_CODE (fld) == FUNCTION_DECL ? 0 : 1),
(DECL_INLINE (fld) ? 1 : 0),
(DECL_FRIEND_P(fld) ? 1 : 0),
(DECL_VINDEX(fld) ? 1 : 0),
(TREE_STATIC(fld) ? 1 : 0),
pure, confg);
}
/* Find file entry given name. */
static XREF_FILE
find_file(name)
char *name;
{
XREF_FILE xf;
for (xf = all_files; xf != NULL; xf = xf->next) {
if (STREQL(name, xf->name)) break;
}
return xf;
}
/* Return filename for output purposes. */
static char *
filename(xf)
XREF_FILE xf;
{
if (xf == NULL) {
last_file = NULL;
return "*";
}
if (last_file == xf) return "*";
last_file = xf;
return xf->outname;
}
/* Return function name for output purposes. */
static char *
fctname(fndecl)
tree fndecl;
{
static char fctbuf[1024];
char *s;
if (fndecl == NULL && last_fndecl == NULL) return "*";
if (fndecl == NULL)
{
last_fndecl = NULL;
return "*TOP*";
}
if (fndecl == last_fndecl) return "*";
last_fndecl = fndecl;
s = declname(fndecl);
s = fixname(s, fctbuf);
return s;
}
/* Return decl name for output purposes. */
static char *
declname(dcl)
tree dcl;
{
if (DECL_NAME (dcl) == NULL) return "?";
if (DECL_ASSEMBLER_NAME (dcl))
return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (dcl));
else
return IDENTIFIER_POINTER (DECL_NAME (dcl));
}
/* Simplify a type string by removing unneeded parenthesis. */
static void
simplify_type(typ)
char *typ;
{
char *s;
int lvl, i;
i = strlen(typ);
while (i > 0 && isspace(typ[i-1])) typ[--i] = 0;
if (i > 7 && STREQL(&typ[i-5], "const"))
{
typ[i-5] = 0;
i -= 5;
}
if (typ[i-1] != ')') return;
s = &typ[i-2];
lvl = 1;
while (*s != 0) {
if (*s == ')') ++lvl;
else if (*s == '(')
{
--lvl;
if (lvl == 0)
{
s[1] = ')';
s[2] = 0;
break;
}
}
--s;
}
if (*s != 0 && s[-1] == ')')
{
--s;
--s;
if (*s == '(') s[2] = 0;
else if (*s == ':') {
while (*s != '(') --s;
s[1] = ')';
s[2] = 0;
}
}
}
/* Fixup a function name (take care of embedded spaces). */
static char *
fixname(nam, buf)
char *nam;
char *buf;
{
char *s, *t;
int fg;
s = nam;
t = buf;
fg = 0;
while (*s != 0)
{
if (*s == ' ')
{
*t++ = '\36';
++fg;
}
else *t++ = *s;
++s;
}
*t = 0;
if (fg == 0) return nam;
return buf;
}
/* Open file for xrefing. */
static void
open_xref_file(file)
char *file;
{
char *s, *t;
#ifdef XREF_FILE_NAME
XREF_FILE_NAME (xref_name, file);
#else
s = rindex (file, '/');
if (s == NULL)
sprintf (xref_name, ".%s.gxref", file);
else
{
++s;
strcpy (xref_name, file);
t = rindex (xref_name, '/');
++t;
*t++ = '.';
strcpy (t, s);
strcat (t, ".gxref");
}
#endif /* no XREF_FILE_NAME */
xref_file = fopen(xref_name, "w");
if (xref_file == NULL)
{
error("Can't create cross-reference file `%s'", xref_name);
doing_xref = 0;
}
}