62nd Cygnus<->FSF merge

From-SVN: r9298
This commit is contained in:
Mike Stump 1995-04-03 19:28:01 +00:00
parent 684cfb6b2f
commit faae18abc2
16 changed files with 720 additions and 358 deletions

View File

@ -1,3 +1,116 @@
Sun Apr 2 23:43:51 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* search.c (compute_access): Don't try to do access control on
nested types.
Fri Mar 31 10:14:23 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* repo.c: New file to handle things repo.
* pt.c (instantiate_template): Call repo_template_used if the
definition is accessible.
(mark_function_instantiated): Split out from
do_function_instantiation.
(mark_class_instantiated): Split out from do_type_instantiation.
* parse.y (template_instantiate_once): Call repo_template_used.
* lex.c (lang_init): Call init_repo.
* decl2.c: Handle flag_use_repository.
(finish_file): Call finish_repo.
* decl.c (start_method): Call repo_template_used if this is a
template method.
* Makefile.in (CXX_OBJS): Add repo.o.
(repo.o): Add dependencies.
* Make-lang.in (CXX_SRCS): Add repo.c.
* decl.c (start_function): If DECL_INTERFACE_KNOWN and
DECL_NOT_REALLY_EXTERN are both set, unset DECL_EXTERNAL.
* typeck.c (build_binary_op_nodefault): Identify the invalid operand
types used.
* decl.c (duplicate_decls): Propagate DECL_NOT_REALLY_EXTERN.
Thu Mar 30 17:54:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_binary_op_nodefault): Tidy up use of build_type
and result_type. When checking for comparison between signed
and unsigned, use result_type rather than the (possibly shortened)
type of op0. Also, don't warn about equality comparison of a
signed operand to an unsigned constant that fits in the signed
type.
* method.c (do_build_copy_constructor): Reverse
current_base_init_list after we've built it up.
Thu Mar 30 14:35:18 1995 Mike Stump <mrs@cygnus.com>
* except.c (build_throw): Never warn about the value of throw not
being used.
Thu Mar 30 13:16:54 1995 Mike Stump <mrs@cygnus.com>
* except.c (expand_start_catch_block): Check for bad catch parameter
declarations.
Thu Mar 30 13:06:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (finish_function): Only set DECL_NOT_REALLY_EXTERN if
DECL_EXTERNAL is not already set.
Thu Mar 30 11:26:24 1995 Mike Stump <mrs@cygnus.com>
* method.c (emit_thunk): Let poplevel know that the last level is
for a function so it can create a BLOCK_NODE and set DECL_INITIAL.
Thu Mar 30 11:15:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl2.c (import_export_inline): Don't set DECL_NOT_REALLY_EXTERN
here.
* decl.c (grokdeclarator): OK, don't abort if we see a decl with
METHOD_TYPE.
(finish_function): Set DECL_EXTERNAL and DECL_NOT_REALLY_EXTERN on
all deferred inlines.
Wed Mar 29 19:35:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* cp-tree.h (DECL_THIS_INLINE): New macro.
(DECL_NOT_REALLY_EXTERN): New macro.
(DECL_THIS_STATIC): New macro.
* decl.c: Lose all references to current_extern_inline. Break
inline semantics into DECL_INLINE for actual inlining and
DECL_THIS_INLINE for the linkage wierdness. Use DECL_THIS_STATIC.
* decl2.c: Use DECL_NOT_REALLY_EXTERN to indicate that we want to
emit an inline here. Associated changes.
* lex.c: Ditto.
* pt.c: Ditto.
* typeck.c: Ditto.
* call.c (build_method_call): Don't bother trying to handle inlines
specially.
* cvt.c (convert_to_aggr): Ditto.
* pt.c (do_function_instantiation): Handle instantiation of
public inlines, too.
Wed Mar 29 16:04:25 1995 Mike Stump <mrs@cygnus.com>
* except.c (init_exception_processing): Change the interface for
__throw_type_match and add decl for new rtti matching routine
__throw_type_match_rtti.
(build_eh_type): New routine to build a run time descriptor for the
expression given.
(expand_start_catch_block): Update to use new calling convention for
the matcher.
(expand_throw): Update to use build_eh_type.
Mon Mar 27 07:14:33 1995 Warner Losh <imp@village.org>
* g++.c: Removed __NetBSD__ from conditional.

View File

@ -76,7 +76,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
$(srcdir)/cp/errfn.c $(srcdir)/cp/gc.c $(srcdir)/cp/method.c \
$(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.c \
$(srcdir)/cp/error.c $(srcdir)/cp/init.c $(srcdir)/cp/parse.y \
$(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c
$(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c $(srcdir)/cp/repo.c
cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus

View File

@ -159,7 +159,7 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
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
edsel.o except.o init.o method.o search.o tree.o xref.o repo.o
# Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
@ -247,6 +247,7 @@ 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) $(srcdir)/../flags.h
repo.o : repo.c $(CONFIG.H) $(CXX_TREE_H)
# These exist for maintenance purposes.

View File

@ -2575,14 +2575,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (TREE_CODE (function) == FUNCTION_DECL)
{
is_constructor = DECL_CONSTRUCTOR_P (function);
if (DECL_INLINE (function))
function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
else
{
assemble_external (function);
TREE_USED (function) = 1;
function = default_conversion (function);
}
TREE_USED (function) = 1;
function = default_conversion (function);
}
else
{

View File

@ -954,9 +954,11 @@ struct lang_decl_flags
unsigned saved_inline : 1;
unsigned use_template : 2;
unsigned declared_static : 1;
unsigned c_static : 1;
unsigned nonconverting : 1;
unsigned dummy : 6;
unsigned declared_inline : 1;
unsigned not_really_extern : 1;
unsigned dummy : 4;
tree access;
tree context;
@ -1234,10 +1236,14 @@ struct lang_decl
#define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), delta2_identifier, 0, 0))
#define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), pfn_identifier, 0, 0))
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `external' was
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
specified in its declaration. */
#define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE))
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `static' was
specified in its declaration. */
#define DECL_THIS_STATIC(NODE) (DECL_LANG_FLAG_6(NODE))
/* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */
#define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE))
@ -1338,13 +1344,26 @@ struct lang_decl
/* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
/* This decl was declared to have internal linkage. */
#define DECL_DECLARED_STATIC(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_static)
/* This decl was declared or deduced to have internal linkage. This is
only meaningful if TREE_PUBLIC is set. */
#define DECL_C_STATIC(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.c_static)
/* This function was declared inline. This flag controls the linkage
semantics of 'inline'; whether or not the function is inlined is
controlled by DECL_INLINE. */
#define DECL_THIS_INLINE(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_inline)
/* DECL_EXTERNAL must be set on a decl until the decl is actually emitted,
so that assemble_external will work properly. So we have this flag to
tell us whether the decl is really not external. */
#define DECL_NOT_REALLY_EXTERN(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern)
#define DECL_PUBLIC(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL ? ! DECL_DECLARED_STATIC (NODE) \
: TREE_PUBLIC (NODE))
(TREE_CODE (NODE) == FUNCTION_DECL \
? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE))
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)

View File

@ -1090,10 +1090,7 @@ convert_to_aggr (type, expr, msgp, protect)
return NULL_TREE;
fntype = TREE_TYPE (function);
if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL)
function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
else
function = default_conversion (function);
function = default_conversion (function);
result = build_nt (CALL_EXPR, function,
convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),

View File

@ -406,10 +406,6 @@ tree current_function_return_value;
static int warn_about_return_type;
/* Nonzero when starting a function declared `extern inline'. */
static int current_extern_inline;
/* Nonzero means give `double' the same size as `float'. */
extern int flag_short_double;
@ -2082,13 +2078,11 @@ warn_extern_redeclared_static (newdecl, olddecl)
= "`%D' was declared implicitly `extern' and later `static'";
if (flag_traditional
|| TREE_CODE (newdecl) == TYPE_DECL
|| (! warn_extern_inline
&& DECL_INLINE (newdecl)))
|| TREE_CODE (newdecl) == TYPE_DECL)
return;
name = DECL_ASSEMBLER_NAME (newdecl);
if (TREE_PUBLIC (name) && ! DECL_PUBLIC (newdecl))
if (TREE_PUBLIC (name) && DECL_THIS_STATIC (newdecl))
{
/* It's okay to redeclare an ANSI built-in function as static,
or to declare a non-ANSI built-in function as anything. */
@ -2516,8 +2510,9 @@ duplicate_decls (newdecl, olddecl)
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_DECLARED_STATIC (newdecl) = DECL_DECLARED_STATIC (olddecl);
DECL_C_STATIC (newdecl) = DECL_C_STATIC (olddecl);
DECL_INTERFACE_KNOWN (newdecl) = DECL_INTERFACE_KNOWN (olddecl);
DECL_NOT_REALLY_EXTERN (newdecl) = DECL_NOT_REALLY_EXTERN (olddecl);
}
}
else
@ -2537,14 +2532,16 @@ duplicate_decls (newdecl, olddecl)
}
}
/* If either decl says `inline', this fn is inline,
unless its definition was passed already. */
if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
DECL_INLINE (olddecl) = 1;
DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl);
/* If either decl says `inline', this fn is inline, unless its
definition was passed already. */
if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
DECL_INLINE (olddecl) = 1;
DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
if (! types_match)
{
DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
@ -2968,7 +2965,7 @@ pushdecl (x)
/* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */
if (oldlocal == NULL_TREE
&& DECL_EXTERNAL (x) && !DECL_INLINE (x)
&& DECL_EXTERNAL (x)
&& oldglobal != NULL_TREE
&& TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL)
@ -3454,11 +3451,7 @@ redeclaration_error_message (newdecl, olddecl)
/* defining the same name twice is no good. */
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE
/* However, defining once as extern inline and a second
time in another way is ok. */
&& !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
&& !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
if (DECL_NAME (olddecl) == NULL_TREE)
return "`%#D' not declared in class";
@ -6393,55 +6386,7 @@ finish_decl (decl, init, asmspec_tree, need_pop, flags)
signature_error (decl, TREE_TYPE (type));
if (TREE_CODE (decl) == FUNCTION_DECL)
{
#if 0
/* C++: Handle overloaded functions with default parameters. */
if (DECL_OVERLOADED (decl))
{
tree parmtypes = TYPE_ARG_TYPES (type);
tree prev = NULL_TREE;
tree original_name = DECL_NAME (decl);
struct lang_decl *tmp_lang_decl = DECL_LANG_SPECIFIC (decl);
/* All variants will share an uncollectible lang_decl. */
copy_decl_lang_specific (decl);
while (parmtypes && parmtypes != void_list_node)
{
/* The default value for the parameter in parmtypes is
stored in the TREE_PURPOSE of the TREE_LIST. */
if (TREE_PURPOSE (parmtypes))
{
tree fnname, fndecl;
tree *argp;
argp = prev ? & TREE_CHAIN (prev)
: & TYPE_ARG_TYPES (type);
*argp = NULL_TREE;
fnname = build_decl_overload (original_name,
TYPE_ARG_TYPES (type), 0);
*argp = parmtypes;
fndecl = build_decl (FUNCTION_DECL, fnname, type);
DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl);
TREE_PUBLIC (fndecl) = TREE_PUBLIC (decl);
DECL_INLINE (fndecl) = DECL_INLINE (decl);
/* Keep G++ from thinking this function is unused.
It is only used to speed up search in name space. */
TREE_USED (fndecl) = 1;
TREE_ASM_WRITTEN (fndecl) = 1;
DECL_INITIAL (fndecl) = NULL_TREE;
DECL_LANG_SPECIFIC (fndecl) = DECL_LANG_SPECIFIC (decl);
fndecl = pushdecl (fndecl);
DECL_INITIAL (fndecl) = error_mark_node;
DECL_RTL (fndecl) = DECL_RTL (decl);
}
prev = parmtypes;
parmtypes = TREE_CHAIN (parmtypes);
}
DECL_LANG_SPECIFIC (decl) = tmp_lang_decl;
}
#endif
}
;
else if (DECL_EXTERNAL (decl))
;
else if (TREE_STATIC (decl) && type != error_mark_node)
@ -6775,13 +6720,13 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
not look, and -1 if we should not call `grokclassfn' at all. */
static tree
grokfndecl (ctype, type, declarator, virtualp, flags, quals,
raises, check, publicp)
raises, check, publicp, inlinep)
tree ctype, type;
tree declarator;
int virtualp;
enum overload_flags flags;
tree quals, raises;
int check, publicp;
int check, publicp, inlinep;
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@ -6814,10 +6759,21 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
definition or EOF) if appropriate. */
TREE_PUBLIC (decl) = 1;
if (publicp)
;
else
DECL_DECLARED_STATIC (decl) = 1;
if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
{
if (inlinep)
error ("cannot declare `main' to be inline");
else if (! publicp)
error ("cannot declare `main' to be static");
inlinep = 0;
publicp = 1;
}
if (! publicp)
DECL_C_STATIC (decl) = 1;
if (inlinep)
DECL_THIS_INLINE (decl) = DECL_INLINE (decl) = 1;
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
@ -9060,37 +9016,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
publicp = (RIDBIT_SETP (RID_EXTERN, specbits)
|| (ctype != NULL_TREE
&& funcdef_flag >= 0
&& RIDBIT_NOTSETP (RID_INLINE, specbits))
|| (friendp
&& ! funcdef_flag
&& RIDBIT_NOTSETP (RID_STATIC, specbits)
&& RIDBIT_NOTSETP (RID_INLINE, specbits)));
publicp = (! friendp
|| RIDBIT_SETP (RID_EXTERN, specbits)
|| ! (funcdef_flag < 0 || inlinep));
decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals,
raises, friendp ? -1 : 0, publicp);
raises, friendp ? -1 : 0, publicp, inlinep);
if (decl == NULL_TREE)
return NULL_TREE;
decl = build_decl_attribute_variant (decl, decl_machine_attr);
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
DECL_INLINE (decl) = inlinep;
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
/* We only get here for friend declarations of
members of other classes. */
/* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals,
raises, friendp ? -1 : 0, 1);
raises, friendp ? -1 : 0, 1, 0);
if (decl == NULL_TREE)
return NULL_TREE;
DECL_INLINE (decl) = inlinep;
}
else if (TYPE_SIZE (type) == NULL_TREE && !staticp
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
@ -9255,16 +9204,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
TREE_TYPE (type), TYPE_ARG_TYPES (type));
/* Record presence of `static'. In C++, `inline' is like `static'. */
publicp
= !(RIDBIT_SETP (RID_STATIC, specbits)
|| RIDBIT_SETP (RID_INLINE, specbits));
/* Record presence of `static'. In C++, `inline' implies `static'. */
publicp = (ctype != NULL_TREE
|| (!RIDBIT_SETP (RID_STATIC, specbits)
&& !RIDBIT_SETP (RID_INLINE, specbits)));
decl = grokfndecl (ctype, type, original_name,
virtualp, flags, quals,
raises,
processing_template_decl ? 0 : friendp ? 2 : 1,
publicp);
publicp, inlinep);
if (decl == NULL_TREE)
return NULL_TREE;
@ -9282,14 +9231,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl);
illegal_static = 1;
}
else if (! ctype
&& IDENTIFIER_LENGTH (original_name) == 4
&& IDENTIFIER_POINTER (original_name)[0] == 'm'
&& ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
{
error ("cannot declare function `main' to have static linkage");
illegal_static = 1;
}
else if (current_function_decl)
{
/* FIXME need arm citation */
@ -9303,28 +9244,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
RIDBIT_RESET (RID_STATIC, specbits);
}
}
/* Record presence of `inline', if it is reasonable. */
if (inlinep)
{
tree last = tree_last (TYPE_ARG_TYPES (type));
if (! ctype
&& ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
error ("cannot inline function `main'");
else if (last && last != void_list_node)
cp_warning ("cannot inline function `%D' which takes `...'", original_name);
else
/* Assume that otherwise the function can be inlined. */
DECL_INLINE (decl) = 1;
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
current_extern_inline = 1;
if (pedantic)
pedwarn ("ANSI C++ does not permit `extern inline'");
}
}
}
else
{
@ -9398,6 +9317,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (RIDBIT_SETP (RID_EXTERN, specbits))
DECL_THIS_EXTERN (decl) = 1;
if (RIDBIT_SETP (RID_STATIC, specbits))
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. */
if (constp)
@ -10723,7 +10645,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
current_function_returns_value = 0;
current_function_returns_null = 0;
warn_about_return_type = 0;
current_extern_inline = 0;
current_function_assigns_this = 0;
current_function_just_assigned_this = 0;
current_function_parms_stored = 0;
@ -10781,11 +10702,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
doing_friend = 1;
}
if ( !(DECL_VINDEX (decl1)
&& write_virtuals >= 2
&& CLASSTYPE_VTABLE_NEEDS_WRITING (ctype)))
current_extern_inline = DECL_THIS_EXTERN (decl1) && DECL_INLINE (decl1);
raises = TYPE_RAISES_EXCEPTIONS (fntype);
/* In a fcn definition, arg types must be complete. */
@ -10890,18 +10806,21 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
TREE_STATIC (decl1) = 1;
if (DECL_INTERFACE_KNOWN (decl1))
/* We know. */;
{
if (DECL_NOT_REALLY_EXTERN (decl1))
DECL_EXTERNAL (decl1) = 0;
}
/* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external.
It doesn't matter whether it's inline or not. */
else if (interface_unknown == 0)
{
if (DECL_DECLARED_STATIC (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
DECL_EXTERNAL (decl1)
= (interface_only
|| (DECL_INLINE (decl1) && ! flag_implement_inlines));
|| (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
else
DECL_EXTERNAL (decl1) = current_extern_inline;
DECL_EXTERNAL (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
}
else
@ -10909,19 +10828,15 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
/* This is a definition, not a reference.
So clear DECL_EXTERNAL. */
DECL_EXTERNAL (decl1) = 0;
if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1)
|| current_extern_inline))
/* We know nothing yet */;
if (DECL_THIS_INLINE (decl1) && ! DECL_C_STATIC (decl1))
DECL_DEFER_OUTPUT (decl1) = 1;
else
{
DECL_INTERFACE_KNOWN (decl1) = 1;
if (DECL_DECLARED_STATIC (decl1))
if (DECL_C_STATIC (decl1))
TREE_PUBLIC (decl1) = 0;
}
DECL_DEFER_OUTPUT (decl1) = ! DECL_INTERFACE_KNOWN (decl1);
}
/* Record the decl so that the function name is defined.
@ -11728,9 +11643,10 @@ finish_function (lineno, call_poplevel, nested)
if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
{
/* Set DECL_EXTERNAL so that assemble_external will be called as
necessary. We'll clear it again in import_export_inline. */
if (TREE_PUBLIC (fndecl))
DECL_EXTERNAL (fndecl) = 1;
necessary. We'll clear it again in finish_file. */
if (! DECL_EXTERNAL (fndecl))
DECL_NOT_REALLY_EXTERN (fndecl) = 1;
DECL_EXTERNAL (fndecl) = 1;
mark_inline_for_output (fndecl);
}
@ -11857,11 +11773,16 @@ start_method (declspecs, declarator, raises)
return void_type_node;
}
DECL_THIS_INLINE (fndecl) = 1;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
if (processing_template_defn)
SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
{
SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
repo_template_used (fndecl);
}
/* We read in the parameters on the maybepermanent_obstack,
but we won't be getting back to them until after we
@ -12207,7 +12128,6 @@ struct cp_function
int returns_value;
int returns_null;
int warn_about_return_type;
int extern_inline;
int assigns_this;
int just_assigned_this;
int parms_stored;
@ -12247,7 +12167,6 @@ push_cp_function_context (context)
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
p->warn_about_return_type = warn_about_return_type;
p->extern_inline = current_extern_inline;
p->binding_level = current_binding_level;
p->ctor_label = ctor_label;
p->dtor_label = dtor_label;
@ -12295,7 +12214,6 @@ pop_cp_function_context (context)
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
warn_about_return_type = p->warn_about_return_type;
current_extern_inline = p->extern_inline;
current_binding_level = p->binding_level;
ctor_label = p->ctor_label;
dtor_label = p->dtor_label;

View File

@ -148,6 +148,10 @@ int warn_ctor_dtor_privacy = 1;
int flag_vtable_thunks;
/* True if we want to deal with repository information. */
int flag_use_repository;
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */
@ -399,7 +403,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0},
{"operator-names", &flag_operator_names, 1},
{"check-new", &flag_check_new, 1}
{"check-new", &flag_check_new, 1},
{"repo", &flag_use_repository, 1}
};
/* Decode the string P as a language-specific option.
@ -2466,13 +2471,7 @@ mark_vtable_entries (decl)
fnaddr = TREE_VALUE (entries);
TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
}
if (TREE_PUBLIC (fn) && ! TREE_ASM_WRITTEN (fn))
{
int save_extern = DECL_EXTERNAL (fn);
DECL_EXTERNAL (fn) = 1;
assemble_external (fn);
DECL_EXTERNAL (fn) = save_extern;
}
assemble_external (fn);
}
}
@ -2513,12 +2512,11 @@ import_export_vtable (decl, type, final)
if (! found && ! final)
{
/* This check only works before the method definitions are seen,
since DECL_INLINE may get bashed. */
tree method;
for (method = CLASSTYPE_METHODS (type); method != NULL_TREE;
method = DECL_NEXT_METHOD (method))
if (DECL_VINDEX (method) != NULL_TREE && ! DECL_INLINE (method)
if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_THIS_INLINE (method)
&& ! DECL_ABSTRACT_VIRTUAL_P (method))
{
found = 1;
@ -2528,15 +2526,17 @@ import_export_vtable (decl, type, final)
if (final || ! found)
{
#ifdef ASSEMBLE_EXTERNAL
if (TREE_PUBLIC (decl))
cp_error ("all virtual functions redeclared inline");
#endif
TREE_PUBLIC (decl) = 0;
DECL_EXTERNAL (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
}
else
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_INTERFACE_KNOWN (decl) = 0;
}
}
}
@ -2570,7 +2570,7 @@ finish_prevtable_vardecl (prev, vars)
method = DECL_NEXT_METHOD (method))
{
if (DECL_VINDEX (method) != NULL_TREE
&& !DECL_DECLARED_STATIC (method)
&& !DECL_THIS_INLINE (method)
&& !DECL_ABSTRACT_VIRTUAL_P (method))
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
@ -2747,23 +2747,21 @@ import_export_inline (decl)
if (DECL_INTERFACE_KNOWN (decl))
return;
DECL_EXTERNAL (decl) = 0;
if (DECL_TEMPLATE_INSTANTIATION (decl))
{
if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
TREE_PUBLIC (decl) = 0;
else
DECL_EXTERNAL (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 0;
}
else if (DECL_FUNCTION_MEMBER_P (decl))
{
tree ctype = DECL_CLASS_CONTEXT (decl);
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{
DECL_EXTERNAL (decl)
= (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_INLINE (decl) && ! flag_implement_inlines));
DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
}
else
TREE_PUBLIC (decl) = 0;
@ -3045,6 +3043,8 @@ finish_file ()
assemble_constructor (IDENTIFIER_POINTER (fnname));
}
permanent_allocation (1);
/* Done with C language context needs. */
pop_lang_context ();
@ -3115,8 +3115,9 @@ finish_file ()
{
TREE_CHAIN (last) = TREE_CHAIN (place);
if (! DECL_EXTERNAL (decl))
if (DECL_NOT_REALLY_EXTERN (decl))
{
DECL_EXTERNAL (decl) = 0;
reconsider = 1;
temporary_allocation ();
output_inline_function (decl);
@ -3142,7 +3143,7 @@ finish_file ()
emit_thunk (vars);
else if (TREE_CODE (vars) == FUNCTION_DECL
&& ! DECL_INTERFACE_KNOWN (vars)
&& DECL_DECLARED_STATIC (vars))
&& DECL_C_STATIC (vars))
TREE_PUBLIC (vars) = 0;
}
@ -3162,7 +3163,8 @@ finish_file ()
}
}
permanent_allocation (1);
finish_repo ();
this_time = get_run_time ();
parse_time -= this_time - start_time;
varconst_time += this_time - start_time;

View File

@ -780,9 +780,14 @@ init_exception_processing ()
push_lang_context (lang_name_c);
catch_match_fndecl =
define_function ("__throw_type_match",
build_function_type (integer_type_node,
tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node))),
define_function (flag_rtti
? "__throw_type_match_rtti"
: "__throw_type_match",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
void_list_node)))),
NOT_BUILT_IN,
pushdecl,
0);
@ -1131,6 +1136,31 @@ expand_leftover_cleanups ()
}
}
/* Build a type value for use at runtime for a exp that is thrown or
matched against by the exception handling system. */
static tree
build_eh_type (exp)
tree exp;
{
char *typestring;
tree type;
if (flag_rtti)
{
exp = build_typeid (exp);
return build1 (ADDR_EXPR, ptr_type_node, exp);
}
type = TREE_TYPE (exp);
/* peel back references, so they match. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
typestring = build_overload_name (type, 1, 1);
exp = combine_strings (build_string (strlen (typestring)+1, typestring));
return build1 (ADDR_EXPR, ptr_type_node, exp);
}
/* call this to start a catch block. Typename is the typename, and identifier
is the variable to place the object in or NULL if the variable doesn't
matter. If typename is NULL, that means its a "catch (...)" or catch
@ -1142,8 +1172,7 @@ expand_start_catch_block (declspecs, declarator)
{
rtx false_label_rtx;
rtx protect_label_rtx;
tree type;
tree decl;
tree decl = NULL_TREE;
tree init;
if (! doing_eh (1))
@ -1152,33 +1181,6 @@ expand_start_catch_block (declspecs, declarator)
/* Create a binding level for the parm. */
expand_start_bindings (0);
if (declspecs)
{
tree init_type;
decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
/* Figure out the type that the initializer is. */
init_type = TREE_TYPE (decl);
if (TREE_CODE (init_type) != REFERENCE_TYPE)
init_type = build_reference_type (init_type);
init = convert_from_reference (save_expr (make_tree (init_type, saved_throw_value)));
/* Do we need the below two lines? */
/* Let `finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
/* This needs to be preallocated under the try block,
in a union of all catch variables. */
pushdecl (decl);
type = TREE_TYPE (decl);
/* peel back references, so they match. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
}
else
type = NULL_TREE;
/* These are saved for the exception table. */
push_rtl_perm ();
false_label_rtx = gen_label_rtx ();
@ -1187,34 +1189,50 @@ expand_start_catch_block (declspecs, declarator)
push_label_entry (&false_label_stack, false_label_rtx);
push_label_entry (&false_label_stack, protect_label_rtx);
if (type)
if (declspecs)
{
tree params;
char *typestring;
tree exp;
rtx call_rtx, return_value_rtx;
tree catch_match_fcall;
tree catchmatch_arg, argval;
tree init_type;
typestring = build_overload_name (type, 1, 1);
decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
params = tree_cons (NULL_TREE,
combine_strings (build_string (strlen (typestring)+1, typestring)),
tree_cons (NULL_TREE,
make_tree (ptr_type_node, saved_throw_type),
NULL_TREE));
catch_match_fcall = build_function_call (CatchMatch, params);
call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0);
if (decl == NULL_TREE)
{
error ("invalid catch parameter");
return;
}
/* Figure out the type that the initializer is. */
init_type = TREE_TYPE (decl);
if (TREE_CODE (init_type) != REFERENCE_TYPE)
init_type = build_reference_type (init_type);
exp = make_tree (ptr_type_node, saved_throw_value);
exp = tree_cons (NULL_TREE,
build_eh_type (decl),
tree_cons (NULL_TREE,
make_tree (ptr_type_node, saved_throw_type),
tree_cons (NULL_TREE, exp, NULL_TREE)));
exp = build_function_call (CatchMatch, exp);
call_rtx = expand_call (exp, NULL_RTX, 0);
assemble_external (TREE_OPERAND (CatchMatch, 0));
return_value_rtx =
hard_function_value (integer_type_node, catch_match_fcall);
return_value_rtx = hard_function_value (ptr_type_node, exp);
/* did the throw type match function return TRUE? */
emit_cmp_insn (return_value_rtx, const0_rtx, NE, NULL_RTX,
emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
GET_MODE (return_value_rtx), 0, 0);
/* if it returned FALSE, jump over the catch block, else fall into it */
emit_jump_insn (gen_bne (false_label_rtx));
emit_jump_insn (gen_beq (false_label_rtx));
init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
/* Do we need the below two lines? */
/* Let `finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
decl = pushdecl (decl);
finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
}
else
@ -1535,7 +1553,6 @@ expand_throw (exp)
tree exp;
{
rtx label;
tree type;
if (! doing_eh (1))
return;
@ -1548,26 +1565,28 @@ expand_throw (exp)
if (exp)
{
tree throw_type;
rtx throw_type_rtx;
rtx throw_value_rtx;
/* throw expression */
/* First, decay it. */
exp = default_conversion (exp);
type = TREE_TYPE (exp);
{
char *typestring = build_overload_name (type, 1, 1);
tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring)));
rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
rtx throw_value_rtx;
/* Make a copy of the thrown object. WP 15.1.5 */
exp = build_new (NULL_TREE, TREE_TYPE (exp),
build_tree_list (NULL_TREE, exp),
0);
/* Make a copy of the thrown object. WP 15.1.5 */
exp = build_new (NULL_TREE, type, build_tree_list (NULL_TREE, exp), 0);
if (exp == error_mark_node)
error (" in thrown expression");
if (exp == error_mark_node)
error (" in thrown expression");
throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
emit_move_insn (saved_throw_value, throw_value_rtx);
emit_move_insn (saved_throw_type, throw_type_rtx);
}
throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR));
throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
emit_move_insn (saved_throw_value, throw_value_rtx);
emit_move_insn (saved_throw_type, throw_type_rtx);
}
else
{
@ -1665,6 +1684,7 @@ build_throw (e)
{
e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1;
TREE_USED (e) = 1;
}
return e;
}

View File

@ -362,6 +362,7 @@ lang_init ()
if (flag_cadillac)
cadillac_start ();
if (flag_gnu_xref) GNU_xref_begin (input_filename);
init_repo (input_filename);
}
void
@ -1448,7 +1449,7 @@ store_pending_inline (decl, t)
punt them now, or output them now if we're doing implementations
and we know no overrides will exist. Otherwise, we delay until
end-of-file, to see if the definition is really required. */
if (DECL_INLINE (decl))
if (DECL_THIS_INLINE (decl))
/* delay_to_eof == 0 */;
else if (current_class_type && !interface_unknown)
{

View File

@ -1936,7 +1936,7 @@ emit_thunk (thunk_fndecl)
emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
expand_end_bindings (NULL, 1, 0);
poplevel (0, 0, 0);
poplevel (0, 0, 1);
/* From now on, allocate rtl in current_obstack, not in saveable_obstack.
Note that that may have been done above, in save_for_inline_copying.
@ -2122,6 +2122,7 @@ do_build_copy_constructor (fndecl)
= tree_cons (DECL_NAME (fields), init, current_member_init_list);
}
current_member_init_list = nreverse (current_member_init_list);
current_base_init_list = nreverse (current_base_init_list);
setup_vtbl_ptr ();
}

View File

@ -897,6 +897,8 @@ template_instantiate_once:
pop_obstacks ();
end_template_instantiation ($1);
repo_template_used (t);
/* Now go after the methods & class data. */
instantiate_member_templates ($1);

View File

@ -1450,6 +1450,7 @@ tsubst (t, args, nargs, in_decl)
TREE_STATIC (r) = 0;
DECL_INTERFACE_KNOWN (r) = 0;
DECL_INLINE (r) = DECL_INLINE (t);
DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t);
{
#if 0 /* Maybe later. -jason */
struct tinst_level *til = tinst_for_decl();
@ -1751,6 +1752,7 @@ instantiate_template (tmpl, targ_ptr)
else if (t->text)
{
SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
repo_template_used (fndecl);
p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
p->parm_vec = t->parm_vec;
p->bindings = targs;
@ -2384,7 +2386,7 @@ do_pending_expansions ()
DECIDE (0);
if (DECL_EXPLICIT_INSTANTIATION (t))
DECIDE (! DECL_EXTERNAL (t));
DECIDE (DECL_NOT_REALLY_EXTERN (t));
else if (! flag_implicit_templates)
DECIDE (0);
@ -2486,6 +2488,22 @@ add_pending_template (pt)
p->id = pt;
}
void
mark_function_instantiated (result, extern_p)
tree result;
int extern_p;
{
if (DECL_TEMPLATE_INSTANTIATION (result))
SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
if (! extern_p)
{
DECL_INTERFACE_KNOWN (result) = 1;
DECL_NOT_REALLY_EXTERN (result) = 1;
}
}
/* called from the parser. */
void
do_function_instantiation (declspecs, declarator, storage)
@ -2495,10 +2513,17 @@ do_function_instantiation (declspecs, declarator, storage)
tree name = DECL_NAME (decl);
tree fn = IDENTIFIER_GLOBAL_VALUE (name);
tree result = NULL_TREE;
int extern_p = 0;
if (fn)
{
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
if (TREE_CODE (fn) == TEMPLATE_DECL)
if (decls_match (fn, decl)
&& DECL_DEFER_OUTPUT (fn))
{
result = fn;
break;
}
else if (TREE_CODE (fn) == TEMPLATE_DECL)
{
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
@ -2518,27 +2543,40 @@ do_function_instantiation (declspecs, declarator, storage)
}
}
if (! result)
cp_error ("no matching template for `%D' found", decl);
{
cp_error ("no matching template for `%D' found", decl);
return;
}
if (flag_external_templates)
return;
SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
if (storage == NULL_TREE)
{
DECL_INTERFACE_KNOWN (result) = 1;
DECL_EXTERNAL (result) = 0;
TREE_STATIC (result) = 1;
}
else if (storage == ridpointers[(int) RID_EXTERN])
;
else if (storage == ridpointers[(int) RID_EXTERN])
extern_p = 1;
else
cp_error ("storage class `%D' applied to template instantiation",
storage);
mark_function_instantiated (result, extern_p);
}
void
mark_class_instantiated (t, extern_p)
tree t;
int extern_p;
{
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p;
if (! extern_p)
{
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
rest_of_type_compilation (t, 1);
}
}
void
do_type_instantiation (name, storage)
tree name, storage;
@ -2578,18 +2616,7 @@ do_type_instantiation (name, storage)
}
if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
{
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p;
if (! extern_p)
{
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
rest_of_type_compilation (t, 1);
}
}
mark_class_instantiated (t, extern_p);
{
tree tmp;
@ -2615,8 +2642,7 @@ do_type_instantiation (name, storage)
if (! extern_p)
{
DECL_INTERFACE_KNOWN (tmp) = 1;
DECL_EXTERNAL (tmp) = 0;
TREE_STATIC (tmp) = 1;
DECL_NOT_REALLY_EXTERN (tmp) = 1;
}
}

278
gcc/cp/repo.c Normal file
View File

@ -0,0 +1,278 @@
/* Code to maintain a C++ template repository.
Copyright (C) 1995 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. */
/* My strategy here is as follows:
Everything should be emitted in a translation unit where it is used.
The results of the automatic process should be easily reproducible with
explicit code.
I'm thinking of compiling with -frepo, running a Perl script to update
files, and then being able to rebuild everything with -fno-implicit.
Full automation can come later. */
#include <stdio.h>
#include "tree.h"
#include "cp-tree.h"
#include "input.h"
extern char * rindex ();
static tree pending_repo;
static char repo_name[1024];
static FILE *repo_file;
extern int flag_use_repository;
extern int errorcount, sorrycount;
static int repo_changed;
#define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE))
#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
/* Record the flags used to compile this translation unit. */
void
repo_compile_flags (argc, argv)
int argc;
char **argv;
{
}
/* If this template has not been seen before, add a note to the repository
saying where the declaration was. This may be used to find the
definition at link time. */
void
repo_template_declared (t)
tree t;
{}
/* Note where the definition of a template lives so that instantiations can
be generated later. */
void
repo_template_defined (t)
tree t;
{}
/* Note where the definition of a class lives to that template
instantiations can use it. */
void
repo_class_defined (t)
tree t;
{}
/* Note that a template has been used. If we can see the definition, offer
to emit it. */
void
repo_template_used (t)
tree t;
{
tree id;
if (! flag_use_repository)
return;
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
id = DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t));
if (IDENTIFIER_REPO_CHOSEN (id))
mark_class_instantiated (t, 0);
}
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
{
id = DECL_ASSEMBLER_NAME (t);
if (IDENTIFIER_REPO_CHOSEN (id))
mark_function_instantiated (t, 0);
}
else
my_friendly_abort (1);
if (! IDENTIFIER_REPO_USED (id))
{
repo_changed = 1;
IDENTIFIER_REPO_USED (id) = 1;
}
pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo);
}
/* Note that the vtable for a class has been used, and offer to emit it. */
void
repo_vtable_used (t)
tree t;
{
if (! flag_use_repository)
return;
pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo);
}
/* Note that an inline with external linkage has been used, and offer to
emit it. */
void
repo_inline_used (fn)
tree fn;
{
if (! flag_use_repository)
return;
/* Member functions of polymorphic classes go with their vtables. */
if (DECL_FUNCTION_MEMBER_P (fn) && TYPE_VIRTUAL_P (DECL_CLASS_CONTEXT (fn)))
{
repo_vtable_used (DECL_CLASS_CONTEXT (fn));
return;
}
pending_repo = perm_tree_cons (NULL_TREE, fn, pending_repo);
}
/* Note that a particular typeinfo node has been used, and offer to
emit it. */
void
repo_tinfo_used (ti)
tree ti;
{
}
static void
open_repo_file (filename)
char *filename;
{
register char *p, *q;
char *file = filename;
char *s = rindex (file, '/');
if (s == NULL)
s = file;
else
++s;
for (p = repo_name, q = file; q < s; )
*p++ = *q++;
*p++ = '.';
strcpy (p, q);
strcat (p, ".repo");
repo_file = fopen (repo_name, "r");
}
void
init_repo (filename)
char *filename;
{
char buf[1024];
if (! flag_use_repository)
return;
open_repo_file (filename);
if (repo_file == 0)
return;
while (fgets (buf, 1024, repo_file))
{
int len = strlen (buf) - 1;
if (buf[len] != '\n')
error ("repository info line too long in %s", repo_name);
buf[len] = '\0';
switch (buf[0])
{
case 'A':
case 'M':
break;
case 'C':
case 'O':
{
tree id = get_identifier (&buf[2]);
IDENTIFIER_REPO_USED (id) = 1;
if (buf[0] == 'C')
IDENTIFIER_REPO_CHOSEN (id) = 1;
}
break;
default:
error ("mysterious repository information in %s", repo_name);
}
}
}
static void
reopen_repo_file_for_write ()
{
if (repo_file)
fclose (repo_file);
repo_file = fopen (repo_name, "w");
if (repo_file == 0)
{
error ("man't create repository information file `%s'", repo_name);
flag_use_repository = 0;
}
}
/* Emit any pending repos. */
void
finish_repo ()
{
tree t;
int changed = 0;
if (! flag_use_repository)
return;
/* Do we have to write out a new info file? */
if (! repo_changed || errorcount || sorrycount)
goto out;
reopen_repo_file_for_write ();
if (repo_file == 0)
goto out;
for (t = pending_repo; t; t = TREE_CHAIN (t))
{
tree val = TREE_VALUE (t);
char type;
if (TREE_CODE_CLASS (TREE_CODE (val)) == 't')
val = TYPE_MAIN_DECL (val);
val = DECL_ASSEMBLER_NAME (val);
if (! IDENTIFIER_REPO_USED (val))
continue;
IDENTIFIER_REPO_USED (val) = 0;
type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O';
fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val));
}
out:
if (repo_file)
fclose (repo_file);
}

View File

@ -793,6 +793,10 @@ compute_access (basetype_path, field)
}
#endif
/* We don't currently support access control on nested types. */
if (TREE_CODE (field) == TYPE_DECL)
return access_public;
previous_scope = current_scope ();
context = DECL_CLASS_CONTEXT (field);

View File

@ -2880,7 +2880,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree build_type = 0;
/* Nonzero means after finally constructing the expression
give it this type. Otherwise, give it type RESULT_TYPE. */
convert it to this type. */
tree final_type = 0;
/* Nonzero if this is an operation like MIN or MAX which can
@ -3155,34 +3155,39 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
if (result_type == NULL_TREE)
result_type = ptr_type_node;
}
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
op1 = null_pointer_node;
result_type = type0;
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
op0 = null_pointer_node;
result_type = type1;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
error ("ANSI C++ forbids comparison between pointer and integer");
op1 = convert (TREE_TYPE (op0), op1);
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
error ("ANSI C++ forbids comparison between pointer and integer");
op0 = convert (TREE_TYPE (op1), op0);
}
else if (TYPE_PTRMEMFUNC_P (type0) && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
{
op0 = build_component_ref (op0, index_identifier, 0, 0);
op1 = integer_zero_node;
result_type = TREE_TYPE (op0);
}
else if (TYPE_PTRMEMFUNC_P (type1) && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
{
op0 = build_component_ref (op1, index_identifier, 0, 0);
op1 = integer_zero_node;
result_type = TREE_TYPE (op0);
}
else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1)
&& (TYPE_PTRMEMFUNC_FN_TYPE (type0)
@ -3258,11 +3263,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
{
return build_binary_op (code, op1, op0, 1);
}
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
if (result_type == NULL_TREE)
result_type = type0;
break;
case MAX_EXPR:
@ -3272,29 +3272,15 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
shorten = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
if (! comp_target_types (type0, type1, 1))
if (comp_target_types (type0, type1, 1))
result_type = common_type (type0, type1);
else
{
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
result_type = ptr_type_node;
}
#if 0
else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
!= (TYPE_SIZE (TREE_TYPE (type1)) != 0))
cp_pedwarn ("comparison of %scomplete and %scomplete pointers",
TYPE_SIZE (TREE_TYPE (type0)) == 0 ? "in" : "",
TYPE_SIZE (TREE_TYPE (type1)) == 0 ? "in" : "",
type0, type1);
else if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions");
#endif
else
result_type = common_type (type0, type1);
}
if (result_type == NULL_TREE)
result_type = type0;
break;
case LE_EXPR:
@ -3307,50 +3293,37 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
if (! comp_target_types (type0, type1, 1))
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
#if 0
else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
!= (TYPE_SIZE (TREE_TYPE (type1)) != 0))
cp_pedwarn ("comparison of %scomplete and %scomplete pointers",
TYPE_SIZE (TREE_TYPE (type0)) == 0 ? "in" : "",
TYPE_SIZE (TREE_TYPE (type1)) == 0 ? "in" : "",
type0, type1);
else if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions");
#endif
else
if (comp_target_types (type0, type1, 1))
result_type = common_type (type0, type1);
else
{
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
result_type = ptr_type_node;
}
}
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
op1 = null_pointer_node;
result_type = type0;
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
op0 = null_pointer_node;
result_type = type1;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
if (pedantic)
pedwarn ("ANSI C++ forbids comparison between pointer and integer");
else if (! flag_traditional)
warning ("comparison between pointer and integer");
op1 = convert (TREE_TYPE (op0), op1);
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
if (pedantic)
pedwarn ("ANSI C++ forbids comparison between pointer and integer");
else if (! flag_traditional)
warning ("comparison between pointer and integer");
op0 = convert (TREE_TYPE (op1), op0);
}
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
if (result_type == NULL_TREE)
result_type = type0;
break;
}
@ -3496,26 +3469,38 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
tree comp_type = TREE_TYPE (op0);
int unsignedp0, unsignedp1;
tree primop0 = get_narrower (op0, &unsignedp0);
tree primop1 = get_narrower (op1, &unsignedp1);
/* Give warnings for comparisons between signed and unsigned
quantities that may fail. Do not warn if the signed quantity
is an unsuffixed integer literal (or some static constant
expression involving such literals) and it is positive.
Do not warn if the comparison is being done in a signed type,
since the signed type will only be chosen if it can represent
all the values of the unsigned type. */
quantities that may fail. */
/* Do the checking based on the original operand trees, so that
casts will be considered, but default promotions won't be. */
if (TREE_UNSIGNED (comp_type)
&& ((op0_signed && (TREE_CODE (orig_op0) != INTEGER_CST
|| tree_int_cst_sgn (orig_op0) == -1))
|| (op1_signed && (TREE_CODE (orig_op1) != INTEGER_CST
|| tree_int_cst_sgn (orig_op1) == -1))))
/* Do not warn if the comparison is being done in a signed type,
since the signed type will only be chosen if it can represent
all the values of the unsigned type. */
if (! TREE_UNSIGNED (result_type))
/* OK */;
/* Do not warn if the signed quantity is an unsuffixed
integer literal (or some static constant expression
involving such literals) and it is non-negative. */
else if ((op0_signed && TREE_CODE (orig_op0) == INTEGER_CST
&& tree_int_cst_sgn (orig_op0) >= 0)
|| (op1_signed && TREE_CODE (orig_op1) == INTEGER_CST
&& tree_int_cst_sgn (orig_op1) >= 0))
/* OK */;
/* Do not warn if the comparison is an equality operation,
the unsigned quantity is an integral constant and it does
not use the most significant bit of result_type. */
else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
&& ((op0_signed && TREE_CODE (orig_op1) == INTEGER_CST
&& int_fits_type_p (orig_op1, signed_type (result_type))
|| (op1_signed && TREE_CODE (orig_op0) == INTEGER_CST
&& int_fits_type_p (orig_op0, signed_type (result_type))))))
/* OK */;
else
warning ("comparison between signed and unsigned");
/* Warn if two unsigned values are being compared in a size
@ -3526,8 +3511,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
have all bits set that are set in the ~ operand when it is
extended. */
else if (TREE_CODE (primop0) == BIT_NOT_EXPR
^ TREE_CODE (primop1) == BIT_NOT_EXPR)
if (TREE_CODE (primop0) == BIT_NOT_EXPR
^ TREE_CODE (primop1) == BIT_NOT_EXPR)
{
if (TREE_CODE (primop0) == BIT_NOT_EXPR)
primop0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
@ -3556,7 +3541,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
}
bits = TYPE_PRECISION (TREE_TYPE (primop));
if (bits < TYPE_PRECISION (comp_type)
if (bits < TYPE_PRECISION (result_type)
&& bits < HOST_BITS_PER_LONG && unsignedp)
{
mask = (~ (HOST_WIDE_INT) 0) << bits;
@ -3566,9 +3551,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
}
else if (unsignedp0 && unsignedp1
&& (TYPE_PRECISION (TREE_TYPE (primop0))
< TYPE_PRECISION (comp_type))
< TYPE_PRECISION (result_type))
&& (TYPE_PRECISION (TREE_TYPE (primop1))
< TYPE_PRECISION (comp_type)))
< TYPE_PRECISION (result_type)))
warning ("comparison of promoted ~unsigned with unsigned");
}
}
@ -3582,7 +3567,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (!result_type)
{
binary_op_error (error_code);
cp_error ("invalid operands `%T' and `%T' to binary `%O'",
TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), error_code);
return error_mark_node;
}
@ -4467,7 +4453,7 @@ mark_addressable (exp)
be non-zero in the case of processing a default function.
The second may be non-zero in the case of a template function. */
x = DECL_MAIN_VARIANT (x);
if ((DECL_INLINE (x) || DECL_PENDING_INLINE_INFO (x))
if ((DECL_THIS_INLINE (x) || DECL_PENDING_INLINE_INFO (x))
&& (DECL_CONTEXT (x) == NULL_TREE
|| TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't'
|| ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x))))