Commit faae18ab by Mike Stump

62nd Cygnus<->FSF merge

From-SVN: r9298
parent 684cfb6b
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> Mon Mar 27 07:14:33 1995 Warner Losh <imp@village.org>
* g++.c: Removed __NetBSD__ from conditional. * g++.c: Removed __NetBSD__ from conditional.
......
...@@ -76,7 +76,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \ ...@@ -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/errfn.c $(srcdir)/cp/gc.c $(srcdir)/cp/method.c \
$(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.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/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 cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus
......
...@@ -159,7 +159,7 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config ...@@ -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 \ 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 \ 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. # Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o 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) ...@@ -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) error.o : error.c $(CONFIG_H) $(CXX_TREE_H)
errfn.o : errfn.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 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. # These exist for maintenance purposes.
......
...@@ -2575,15 +2575,9 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2575,15 +2575,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (TREE_CODE (function) == FUNCTION_DECL) if (TREE_CODE (function) == FUNCTION_DECL)
{ {
is_constructor = DECL_CONSTRUCTOR_P (function); 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; TREE_USED (function) = 1;
function = default_conversion (function); function = default_conversion (function);
} }
}
else else
{ {
is_constructor = 0; is_constructor = 0;
......
...@@ -954,9 +954,11 @@ struct lang_decl_flags ...@@ -954,9 +954,11 @@ struct lang_decl_flags
unsigned saved_inline : 1; unsigned saved_inline : 1;
unsigned use_template : 2; unsigned use_template : 2;
unsigned declared_static : 1; unsigned c_static : 1;
unsigned nonconverting : 1; unsigned nonconverting : 1;
unsigned dummy : 6; unsigned declared_inline : 1;
unsigned not_really_extern : 1;
unsigned dummy : 4;
tree access; tree access;
tree context; tree context;
...@@ -1234,10 +1236,14 @@ struct lang_decl ...@@ -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 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)) #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. */ specified in its declaration. */
#define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE)) #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. */ /* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */
#define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE)) #define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE))
...@@ -1338,13 +1344,26 @@ struct lang_decl ...@@ -1338,13 +1344,26 @@ struct lang_decl
/* We know what we're doing with this decl now. */ /* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE) #define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
/* This decl was declared to have internal linkage. */ /* This decl was declared or deduced to have internal linkage. This is
#define DECL_DECLARED_STATIC(NODE) \ only meaningful if TREE_PUBLIC is set. */
(DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_static) #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) \ #define DECL_PUBLIC(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL ? ! DECL_DECLARED_STATIC (NODE) \ (TREE_CODE (NODE) == FUNCTION_DECL \
: TREE_PUBLIC (NODE)) ? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE))
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i) #define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
......
...@@ -1090,9 +1090,6 @@ convert_to_aggr (type, expr, msgp, protect) ...@@ -1090,9 +1090,6 @@ convert_to_aggr (type, expr, msgp, protect)
return NULL_TREE; return NULL_TREE;
fntype = TREE_TYPE (function); 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, result = build_nt (CALL_EXPR, function,
......
...@@ -406,10 +406,6 @@ tree current_function_return_value; ...@@ -406,10 +406,6 @@ tree current_function_return_value;
static int warn_about_return_type; 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'. */ /* Nonzero means give `double' the same size as `float'. */
extern int flag_short_double; extern int flag_short_double;
...@@ -2082,13 +2078,11 @@ warn_extern_redeclared_static (newdecl, olddecl) ...@@ -2082,13 +2078,11 @@ warn_extern_redeclared_static (newdecl, olddecl)
= "`%D' was declared implicitly `extern' and later `static'"; = "`%D' was declared implicitly `extern' and later `static'";
if (flag_traditional if (flag_traditional
|| TREE_CODE (newdecl) == TYPE_DECL || TREE_CODE (newdecl) == TYPE_DECL)
|| (! warn_extern_inline
&& DECL_INLINE (newdecl)))
return; return;
name = DECL_ASSEMBLER_NAME (newdecl); 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, /* It's okay to redeclare an ANSI built-in function as static,
or to declare a non-ANSI built-in function as anything. */ or to declare a non-ANSI built-in function as anything. */
...@@ -2516,8 +2510,9 @@ duplicate_decls (newdecl, olddecl) ...@@ -2516,8 +2510,9 @@ duplicate_decls (newdecl, olddecl)
if (TREE_CODE (newdecl) == FUNCTION_DECL) 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_INTERFACE_KNOWN (newdecl) = DECL_INTERFACE_KNOWN (olddecl);
DECL_NOT_REALLY_EXTERN (newdecl) = DECL_NOT_REALLY_EXTERN (olddecl);
} }
} }
else else
...@@ -2537,14 +2532,16 @@ duplicate_decls (newdecl, olddecl) ...@@ -2537,14 +2532,16 @@ duplicate_decls (newdecl, olddecl)
} }
} }
/* If either decl says `inline', this fn is inline, if (TREE_CODE (newdecl) == FUNCTION_DECL)
unless its definition was passed already. */ {
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) if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
DECL_INLINE (olddecl) = 1; DECL_INLINE (olddecl) = 1;
DECL_INLINE (newdecl) = DECL_INLINE (olddecl); DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (! types_match) if (! types_match)
{ {
DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl); DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
...@@ -2968,7 +2965,7 @@ pushdecl (x) ...@@ -2968,7 +2965,7 @@ pushdecl (x)
/* If this is an extern function declaration, see if we /* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */ have a global definition or declaration for the function. */
if (oldlocal == NULL_TREE if (oldlocal == NULL_TREE
&& DECL_EXTERNAL (x) && !DECL_INLINE (x) && DECL_EXTERNAL (x)
&& oldglobal != NULL_TREE && oldglobal != NULL_TREE
&& TREE_CODE (x) == FUNCTION_DECL && TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL) && TREE_CODE (oldglobal) == FUNCTION_DECL)
...@@ -3454,11 +3451,7 @@ redeclaration_error_message (newdecl, olddecl) ...@@ -3454,11 +3451,7 @@ redeclaration_error_message (newdecl, olddecl)
/* defining the same name twice is no good. */ /* defining the same name twice is no good. */
if (DECL_INITIAL (olddecl) != NULL_TREE if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != 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))))
{ {
if (DECL_NAME (olddecl) == NULL_TREE) if (DECL_NAME (olddecl) == NULL_TREE)
return "`%#D' not declared in class"; return "`%#D' not declared in class";
...@@ -6393,55 +6386,7 @@ finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -6393,55 +6386,7 @@ finish_decl (decl, init, asmspec_tree, need_pop, flags)
signature_error (decl, TREE_TYPE (type)); signature_error (decl, TREE_TYPE (type));
if (TREE_CODE (decl) == FUNCTION_DECL) 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 (DECL_EXTERNAL (decl))
; ;
else if (TREE_STATIC (decl) && type != error_mark_node) else if (TREE_STATIC (decl) && type != error_mark_node)
...@@ -6775,13 +6720,13 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises) ...@@ -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. */ not look, and -1 if we should not call `grokclassfn' at all. */
static tree static tree
grokfndecl (ctype, type, declarator, virtualp, flags, quals, grokfndecl (ctype, type, declarator, virtualp, flags, quals,
raises, check, publicp) raises, check, publicp, inlinep)
tree ctype, type; tree ctype, type;
tree declarator; tree declarator;
int virtualp; int virtualp;
enum overload_flags flags; enum overload_flags flags;
tree quals, raises; tree quals, raises;
int check, publicp; int check, publicp, inlinep;
{ {
tree cname, decl; tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE; int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
...@@ -6814,10 +6759,21 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, ...@@ -6814,10 +6759,21 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
definition or EOF) if appropriate. */ definition or EOF) if appropriate. */
TREE_PUBLIC (decl) = 1; TREE_PUBLIC (decl) = 1;
if (publicp) if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
; {
else if (inlinep)
DECL_DECLARED_STATIC (decl) = 1; 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; DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE) if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
...@@ -9060,37 +9016,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -9060,37 +9016,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
} }
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
publicp = (RIDBIT_SETP (RID_EXTERN, specbits) publicp = (! friendp
|| (ctype != NULL_TREE || RIDBIT_SETP (RID_EXTERN, specbits)
&& funcdef_flag >= 0 || ! (funcdef_flag < 0 || inlinep));
&& RIDBIT_NOTSETP (RID_INLINE, specbits))
|| (friendp
&& ! funcdef_flag
&& RIDBIT_NOTSETP (RID_STATIC, specbits)
&& RIDBIT_NOTSETP (RID_INLINE, specbits)));
decl = grokfndecl (ctype, type, declarator, decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals, virtualp, flags, quals,
raises, friendp ? -1 : 0, publicp); raises, friendp ? -1 : 0, publicp, inlinep);
if (decl == NULL_TREE) if (decl == NULL_TREE)
return NULL_TREE; return NULL_TREE;
decl = build_decl_attribute_variant (decl, decl_machine_attr); decl = build_decl_attribute_variant (decl, decl_machine_attr);
if (explicitp == 2) if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1; DECL_NONCONVERTING_P (decl) = 1;
DECL_INLINE (decl) = inlinep;
} }
else if (TREE_CODE (type) == METHOD_TYPE) 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 /* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */ TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type, declarator, decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals, virtualp, flags, quals,
raises, friendp ? -1 : 0, 1); raises, friendp ? -1 : 0, 1, 0);
if (decl == NULL_TREE) if (decl == NULL_TREE)
return NULL_TREE; return NULL_TREE;
DECL_INLINE (decl) = inlinep;
} }
else if (TYPE_SIZE (type) == NULL_TREE && !staticp else if (TYPE_SIZE (type) == NULL_TREE && !staticp
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
...@@ -9255,16 +9204,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -9255,16 +9204,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
TREE_TYPE (type), TYPE_ARG_TYPES (type)); TREE_TYPE (type), TYPE_ARG_TYPES (type));
/* Record presence of `static'. In C++, `inline' is like `static'. */ /* Record presence of `static'. In C++, `inline' implies `static'. */
publicp publicp = (ctype != NULL_TREE
= !(RIDBIT_SETP (RID_STATIC, specbits) || (!RIDBIT_SETP (RID_STATIC, specbits)
|| RIDBIT_SETP (RID_INLINE, specbits)); && !RIDBIT_SETP (RID_INLINE, specbits)));
decl = grokfndecl (ctype, type, original_name, decl = grokfndecl (ctype, type, original_name,
virtualp, flags, quals, virtualp, flags, quals,
raises, raises,
processing_template_decl ? 0 : friendp ? 2 : 1, processing_template_decl ? 0 : friendp ? 2 : 1,
publicp); publicp, inlinep);
if (decl == NULL_TREE) if (decl == NULL_TREE)
return NULL_TREE; return NULL_TREE;
...@@ -9282,14 +9231,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -9282,14 +9231,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl); cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl);
illegal_static = 1; 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) else if (current_function_decl)
{ {
/* FIXME need arm citation */ /* FIXME need arm citation */
...@@ -9303,28 +9244,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -9303,28 +9244,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
RIDBIT_RESET (RID_STATIC, specbits); 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 else
{ {
...@@ -9398,6 +9317,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -9398,6 +9317,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (RIDBIT_SETP (RID_EXTERN, specbits)) if (RIDBIT_SETP (RID_EXTERN, specbits))
DECL_THIS_EXTERN (decl) = 1; DECL_THIS_EXTERN (decl) = 1;
if (RIDBIT_SETP (RID_STATIC, specbits))
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. */ /* Record constancy and volatility. */
if (constp) if (constp)
...@@ -10723,7 +10645,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10723,7 +10645,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
current_function_returns_value = 0; current_function_returns_value = 0;
current_function_returns_null = 0; current_function_returns_null = 0;
warn_about_return_type = 0; warn_about_return_type = 0;
current_extern_inline = 0;
current_function_assigns_this = 0; current_function_assigns_this = 0;
current_function_just_assigned_this = 0; current_function_just_assigned_this = 0;
current_function_parms_stored = 0; current_function_parms_stored = 0;
...@@ -10781,11 +10702,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10781,11 +10702,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
doing_friend = 1; 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); raises = TYPE_RAISES_EXCEPTIONS (fntype);
/* In a fcn definition, arg types must be complete. */ /* In a fcn definition, arg types must be complete. */
...@@ -10890,18 +10806,21 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10890,18 +10806,21 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
TREE_STATIC (decl1) = 1; TREE_STATIC (decl1) = 1;
if (DECL_INTERFACE_KNOWN (decl1)) 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 this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external. If it belongs to someone else's interface, it is also external.
It doesn't matter whether it's inline or not. */ It doesn't matter whether it's inline or not. */
else if (interface_unknown == 0) 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) DECL_EXTERNAL (decl1)
= (interface_only = (interface_only
|| (DECL_INLINE (decl1) && ! flag_implement_inlines)); || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
else else
DECL_EXTERNAL (decl1) = current_extern_inline; DECL_EXTERNAL (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1; DECL_INTERFACE_KNOWN (decl1) = 1;
} }
else else
...@@ -10910,18 +10829,14 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10910,18 +10829,14 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
So clear DECL_EXTERNAL. */ So clear DECL_EXTERNAL. */
DECL_EXTERNAL (decl1) = 0; DECL_EXTERNAL (decl1) = 0;
if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1) if (DECL_THIS_INLINE (decl1) && ! DECL_C_STATIC (decl1))
|| DECL_TEMPLATE_INSTANTIATION (decl1) DECL_DEFER_OUTPUT (decl1) = 1;
|| current_extern_inline))
/* We know nothing yet */;
else else
{ {
DECL_INTERFACE_KNOWN (decl1) = 1; DECL_INTERFACE_KNOWN (decl1) = 1;
if (DECL_DECLARED_STATIC (decl1)) if (DECL_C_STATIC (decl1))
TREE_PUBLIC (decl1) = 0; TREE_PUBLIC (decl1) = 0;
} }
DECL_DEFER_OUTPUT (decl1) = ! DECL_INTERFACE_KNOWN (decl1);
} }
/* Record the decl so that the function name is defined. /* Record the decl so that the function name is defined.
...@@ -11728,8 +11643,9 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11728,8 +11643,9 @@ finish_function (lineno, call_poplevel, nested)
if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl)) if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
{ {
/* Set DECL_EXTERNAL so that assemble_external will be called as /* Set DECL_EXTERNAL so that assemble_external will be called as
necessary. We'll clear it again in import_export_inline. */ necessary. We'll clear it again in finish_file. */
if (TREE_PUBLIC (fndecl)) if (! DECL_EXTERNAL (fndecl))
DECL_NOT_REALLY_EXTERN (fndecl) = 1;
DECL_EXTERNAL (fndecl) = 1; DECL_EXTERNAL (fndecl) = 1;
mark_inline_for_output (fndecl); mark_inline_for_output (fndecl);
} }
...@@ -11857,11 +11773,16 @@ start_method (declspecs, declarator, raises) ...@@ -11857,11 +11773,16 @@ start_method (declspecs, declarator, raises)
return void_type_node; return void_type_node;
} }
DECL_THIS_INLINE (fndecl) = 1;
if (flag_default_inline) if (flag_default_inline)
DECL_INLINE (fndecl) = 1; DECL_INLINE (fndecl) = 1;
if (processing_template_defn) 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, /* We read in the parameters on the maybepermanent_obstack,
but we won't be getting back to them until after we but we won't be getting back to them until after we
...@@ -12207,7 +12128,6 @@ struct cp_function ...@@ -12207,7 +12128,6 @@ struct cp_function
int returns_value; int returns_value;
int returns_null; int returns_null;
int warn_about_return_type; int warn_about_return_type;
int extern_inline;
int assigns_this; int assigns_this;
int just_assigned_this; int just_assigned_this;
int parms_stored; int parms_stored;
...@@ -12247,7 +12167,6 @@ push_cp_function_context (context) ...@@ -12247,7 +12167,6 @@ push_cp_function_context (context)
p->returns_value = current_function_returns_value; p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null; p->returns_null = current_function_returns_null;
p->warn_about_return_type = warn_about_return_type; p->warn_about_return_type = warn_about_return_type;
p->extern_inline = current_extern_inline;
p->binding_level = current_binding_level; p->binding_level = current_binding_level;
p->ctor_label = ctor_label; p->ctor_label = ctor_label;
p->dtor_label = dtor_label; p->dtor_label = dtor_label;
...@@ -12295,7 +12214,6 @@ pop_cp_function_context (context) ...@@ -12295,7 +12214,6 @@ pop_cp_function_context (context)
current_function_returns_value = p->returns_value; current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null; current_function_returns_null = p->returns_null;
warn_about_return_type = p->warn_about_return_type; warn_about_return_type = p->warn_about_return_type;
current_extern_inline = p->extern_inline;
current_binding_level = p->binding_level; current_binding_level = p->binding_level;
ctor_label = p->ctor_label; ctor_label = p->ctor_label;
dtor_label = p->dtor_label; dtor_label = p->dtor_label;
......
...@@ -148,6 +148,10 @@ int warn_ctor_dtor_privacy = 1; ...@@ -148,6 +148,10 @@ int warn_ctor_dtor_privacy = 1;
int flag_vtable_thunks; 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 *' /* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */ to be useful, except in thoroughly ANSIfied programs. */
...@@ -399,7 +403,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = ...@@ -399,7 +403,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"nonansi-builtins", &flag_no_nonansi_builtin, 0}, {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0}, {"gnu-keywords", &flag_no_gnu_keywords, 0},
{"operator-names", &flag_operator_names, 1}, {"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. /* Decode the string P as a language-specific option.
...@@ -2466,13 +2471,7 @@ mark_vtable_entries (decl) ...@@ -2466,13 +2471,7 @@ mark_vtable_entries (decl)
fnaddr = TREE_VALUE (entries); fnaddr = TREE_VALUE (entries);
TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl; 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); assemble_external (fn);
DECL_EXTERNAL (fn) = save_extern;
}
} }
} }
...@@ -2513,12 +2512,11 @@ import_export_vtable (decl, type, final) ...@@ -2513,12 +2512,11 @@ import_export_vtable (decl, type, final)
if (! found && ! final) if (! found && ! final)
{ {
/* This check only works before the method definitions are seen,
since DECL_INLINE may get bashed. */
tree method; tree method;
for (method = CLASSTYPE_METHODS (type); method != NULL_TREE; for (method = CLASSTYPE_METHODS (type); method != NULL_TREE;
method = DECL_NEXT_METHOD (method)) 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)) && ! DECL_ABSTRACT_VIRTUAL_P (method))
{ {
found = 1; found = 1;
...@@ -2528,15 +2526,17 @@ import_export_vtable (decl, type, final) ...@@ -2528,15 +2526,17 @@ import_export_vtable (decl, type, final)
if (final || ! found) if (final || ! found)
{ {
#ifdef ASSEMBLE_EXTERNAL
if (TREE_PUBLIC (decl))
cp_error ("all virtual functions redeclared inline");
#endif
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
DECL_EXTERNAL (decl) = 0; DECL_EXTERNAL (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
} }
else else
{ {
TREE_PUBLIC (decl) = 1; TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1; DECL_EXTERNAL (decl) = 1;
DECL_INTERFACE_KNOWN (decl) = 0;
} }
} }
} }
...@@ -2570,7 +2570,7 @@ finish_prevtable_vardecl (prev, vars) ...@@ -2570,7 +2570,7 @@ finish_prevtable_vardecl (prev, vars)
method = DECL_NEXT_METHOD (method)) method = DECL_NEXT_METHOD (method))
{ {
if (DECL_VINDEX (method) != NULL_TREE if (DECL_VINDEX (method) != NULL_TREE
&& !DECL_DECLARED_STATIC (method) && !DECL_THIS_INLINE (method)
&& !DECL_ABSTRACT_VIRTUAL_P (method)) && !DECL_ABSTRACT_VIRTUAL_P (method))
{ {
SET_CLASSTYPE_INTERFACE_KNOWN (ctype); SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
...@@ -2747,23 +2747,21 @@ import_export_inline (decl) ...@@ -2747,23 +2747,21 @@ import_export_inline (decl)
if (DECL_INTERFACE_KNOWN (decl)) if (DECL_INTERFACE_KNOWN (decl))
return; return;
DECL_EXTERNAL (decl) = 0;
if (DECL_TEMPLATE_INSTANTIATION (decl)) if (DECL_TEMPLATE_INSTANTIATION (decl))
{ {
if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates) if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
else else
DECL_EXTERNAL (decl) = 1; DECL_NOT_REALLY_EXTERN (decl) = 0;
} }
else if (DECL_FUNCTION_MEMBER_P (decl)) else if (DECL_FUNCTION_MEMBER_P (decl))
{ {
tree ctype = DECL_CLASS_CONTEXT (decl); tree ctype = DECL_CLASS_CONTEXT (decl);
if (CLASSTYPE_INTERFACE_KNOWN (ctype)) if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{ {
DECL_EXTERNAL (decl) DECL_NOT_REALLY_EXTERN (decl)
= (CLASSTYPE_INTERFACE_ONLY (ctype) = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_INLINE (decl) && ! flag_implement_inlines)); || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
} }
else else
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
...@@ -3045,6 +3043,8 @@ finish_file () ...@@ -3045,6 +3043,8 @@ finish_file ()
assemble_constructor (IDENTIFIER_POINTER (fnname)); assemble_constructor (IDENTIFIER_POINTER (fnname));
} }
permanent_allocation (1);
/* Done with C language context needs. */ /* Done with C language context needs. */
pop_lang_context (); pop_lang_context ();
...@@ -3115,8 +3115,9 @@ finish_file () ...@@ -3115,8 +3115,9 @@ finish_file ()
{ {
TREE_CHAIN (last) = TREE_CHAIN (place); TREE_CHAIN (last) = TREE_CHAIN (place);
if (! DECL_EXTERNAL (decl)) if (DECL_NOT_REALLY_EXTERN (decl))
{ {
DECL_EXTERNAL (decl) = 0;
reconsider = 1; reconsider = 1;
temporary_allocation (); temporary_allocation ();
output_inline_function (decl); output_inline_function (decl);
...@@ -3142,7 +3143,7 @@ finish_file () ...@@ -3142,7 +3143,7 @@ finish_file ()
emit_thunk (vars); emit_thunk (vars);
else if (TREE_CODE (vars) == FUNCTION_DECL else if (TREE_CODE (vars) == FUNCTION_DECL
&& ! DECL_INTERFACE_KNOWN (vars) && ! DECL_INTERFACE_KNOWN (vars)
&& DECL_DECLARED_STATIC (vars)) && DECL_C_STATIC (vars))
TREE_PUBLIC (vars) = 0; TREE_PUBLIC (vars) = 0;
} }
...@@ -3162,7 +3163,8 @@ finish_file () ...@@ -3162,7 +3163,8 @@ finish_file ()
} }
} }
permanent_allocation (1); finish_repo ();
this_time = get_run_time (); this_time = get_run_time ();
parse_time -= this_time - start_time; parse_time -= this_time - start_time;
varconst_time += this_time - start_time; varconst_time += this_time - start_time;
......
...@@ -780,9 +780,14 @@ init_exception_processing () ...@@ -780,9 +780,14 @@ init_exception_processing ()
push_lang_context (lang_name_c); push_lang_context (lang_name_c);
catch_match_fndecl = catch_match_fndecl =
define_function ("__throw_type_match", define_function (flag_rtti
build_function_type (integer_type_node, ? "__throw_type_match_rtti"
tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node))), : "__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, NOT_BUILT_IN,
pushdecl, pushdecl,
0); 0);
...@@ -1131,6 +1136,31 @@ expand_leftover_cleanups () ...@@ -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 /* 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 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 matter. If typename is NULL, that means its a "catch (...)" or catch
...@@ -1142,8 +1172,7 @@ expand_start_catch_block (declspecs, declarator) ...@@ -1142,8 +1172,7 @@ expand_start_catch_block (declspecs, declarator)
{ {
rtx false_label_rtx; rtx false_label_rtx;
rtx protect_label_rtx; rtx protect_label_rtx;
tree type; tree decl = NULL_TREE;
tree decl;
tree init; tree init;
if (! doing_eh (1)) if (! doing_eh (1))
...@@ -1152,33 +1181,6 @@ expand_start_catch_block (declspecs, declarator) ...@@ -1152,33 +1181,6 @@ expand_start_catch_block (declspecs, declarator)
/* Create a binding level for the parm. */ /* Create a binding level for the parm. */
expand_start_bindings (0); 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. */ /* These are saved for the exception table. */
push_rtl_perm (); push_rtl_perm ();
false_label_rtx = gen_label_rtx (); false_label_rtx = gen_label_rtx ();
...@@ -1187,34 +1189,50 @@ expand_start_catch_block (declspecs, declarator) ...@@ -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, false_label_rtx);
push_label_entry (&false_label_stack, protect_label_rtx); push_label_entry (&false_label_stack, protect_label_rtx);
if (type) if (declspecs)
{ {
tree params; tree exp;
char *typestring;
rtx call_rtx, return_value_rtx; rtx call_rtx, return_value_rtx;
tree catch_match_fcall; tree init_type;
tree catchmatch_arg, argval;
typestring = build_overload_name (type, 1, 1); decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
params = tree_cons (NULL_TREE, if (decl == NULL_TREE)
combine_strings (build_string (strlen (typestring)+1, typestring)), {
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, tree_cons (NULL_TREE,
make_tree (ptr_type_node, saved_throw_type), make_tree (ptr_type_node, saved_throw_type),
NULL_TREE)); tree_cons (NULL_TREE, exp, NULL_TREE)));
catch_match_fcall = build_function_call (CatchMatch, params); exp = build_function_call (CatchMatch, exp);
call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0); call_rtx = expand_call (exp, NULL_RTX, 0);
assemble_external (TREE_OPERAND (CatchMatch, 0)); assemble_external (TREE_OPERAND (CatchMatch, 0));
return_value_rtx = return_value_rtx = hard_function_value (ptr_type_node, exp);
hard_function_value (integer_type_node, catch_match_fcall);
/* did the throw type match function return TRUE? */ /* 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); GET_MODE (return_value_rtx), 0, 0);
/* if it returned FALSE, jump over the catch block, else fall into it */ /* 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); finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
} }
else else
...@@ -1535,7 +1553,6 @@ expand_throw (exp) ...@@ -1535,7 +1553,6 @@ expand_throw (exp)
tree exp; tree exp;
{ {
rtx label; rtx label;
tree type;
if (! doing_eh (1)) if (! doing_eh (1))
return; return;
...@@ -1548,27 +1565,29 @@ expand_throw (exp) ...@@ -1548,27 +1565,29 @@ expand_throw (exp)
if (exp) if (exp)
{ {
tree throw_type;
rtx throw_type_rtx;
rtx throw_value_rtx;
/* throw expression */ /* throw expression */
/* First, decay it. */ /* First, decay it. */
exp = default_conversion (exp); 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 */ /* Make a copy of the thrown object. WP 15.1.5 */
exp = build_new (NULL_TREE, type, build_tree_list (NULL_TREE, exp), 0); exp = build_new (NULL_TREE, TREE_TYPE (exp),
build_tree_list (NULL_TREE, exp),
0);
if (exp == error_mark_node) if (exp == error_mark_node)
error (" in thrown expression"); error (" in thrown expression");
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); throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
emit_move_insn (saved_throw_value, throw_value_rtx); emit_move_insn (saved_throw_value, throw_value_rtx);
emit_move_insn (saved_throw_type, throw_type_rtx); emit_move_insn (saved_throw_type, throw_type_rtx);
} }
}
else else
{ {
/* rethrow current exception */ /* rethrow current exception */
...@@ -1665,6 +1684,7 @@ build_throw (e) ...@@ -1665,6 +1684,7 @@ build_throw (e)
{ {
e = build1 (THROW_EXPR, void_type_node, e); e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1; TREE_SIDE_EFFECTS (e) = 1;
TREE_USED (e) = 1;
} }
return e; return e;
} }
...@@ -362,6 +362,7 @@ lang_init () ...@@ -362,6 +362,7 @@ lang_init ()
if (flag_cadillac) if (flag_cadillac)
cadillac_start (); cadillac_start ();
if (flag_gnu_xref) GNU_xref_begin (input_filename); if (flag_gnu_xref) GNU_xref_begin (input_filename);
init_repo (input_filename);
} }
void void
...@@ -1448,7 +1449,7 @@ store_pending_inline (decl, t) ...@@ -1448,7 +1449,7 @@ store_pending_inline (decl, t)
punt them now, or output them now if we're doing implementations punt them now, or output them now if we're doing implementations
and we know no overrides will exist. Otherwise, we delay until and we know no overrides will exist. Otherwise, we delay until
end-of-file, to see if the definition is really required. */ end-of-file, to see if the definition is really required. */
if (DECL_INLINE (decl)) if (DECL_THIS_INLINE (decl))
/* delay_to_eof == 0 */; /* delay_to_eof == 0 */;
else if (current_class_type && !interface_unknown) else if (current_class_type && !interface_unknown)
{ {
......
...@@ -1936,7 +1936,7 @@ emit_thunk (thunk_fndecl) ...@@ -1936,7 +1936,7 @@ emit_thunk (thunk_fndecl)
emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count])); emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
expand_end_bindings (NULL, 1, 0); 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. /* 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. Note that that may have been done above, in save_for_inline_copying.
...@@ -2122,6 +2122,7 @@ do_build_copy_constructor (fndecl) ...@@ -2122,6 +2122,7 @@ do_build_copy_constructor (fndecl)
= tree_cons (DECL_NAME (fields), init, current_member_init_list); = tree_cons (DECL_NAME (fields), init, current_member_init_list);
} }
current_member_init_list = nreverse (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 (); setup_vtbl_ptr ();
} }
......
...@@ -897,6 +897,8 @@ template_instantiate_once: ...@@ -897,6 +897,8 @@ template_instantiate_once:
pop_obstacks (); pop_obstacks ();
end_template_instantiation ($1); end_template_instantiation ($1);
repo_template_used (t);
/* Now go after the methods & class data. */ /* Now go after the methods & class data. */
instantiate_member_templates ($1); instantiate_member_templates ($1);
......
...@@ -1450,6 +1450,7 @@ tsubst (t, args, nargs, in_decl) ...@@ -1450,6 +1450,7 @@ tsubst (t, args, nargs, in_decl)
TREE_STATIC (r) = 0; TREE_STATIC (r) = 0;
DECL_INTERFACE_KNOWN (r) = 0; DECL_INTERFACE_KNOWN (r) = 0;
DECL_INLINE (r) = DECL_INLINE (t); DECL_INLINE (r) = DECL_INLINE (t);
DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t);
{ {
#if 0 /* Maybe later. -jason */ #if 0 /* Maybe later. -jason */
struct tinst_level *til = tinst_for_decl(); struct tinst_level *til = tinst_for_decl();
...@@ -1751,6 +1752,7 @@ instantiate_template (tmpl, targ_ptr) ...@@ -1751,6 +1752,7 @@ instantiate_template (tmpl, targ_ptr)
else if (t->text) else if (t->text)
{ {
SET_DECL_IMPLICIT_INSTANTIATION (fndecl); SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
repo_template_used (fndecl);
p = (struct pending_inline *) permalloc (sizeof (struct pending_inline)); p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
p->parm_vec = t->parm_vec; p->parm_vec = t->parm_vec;
p->bindings = targs; p->bindings = targs;
...@@ -2384,7 +2386,7 @@ do_pending_expansions () ...@@ -2384,7 +2386,7 @@ do_pending_expansions ()
DECIDE (0); DECIDE (0);
if (DECL_EXPLICIT_INSTANTIATION (t)) if (DECL_EXPLICIT_INSTANTIATION (t))
DECIDE (! DECL_EXTERNAL (t)); DECIDE (DECL_NOT_REALLY_EXTERN (t));
else if (! flag_implicit_templates) else if (! flag_implicit_templates)
DECIDE (0); DECIDE (0);
...@@ -2486,6 +2488,22 @@ add_pending_template (pt) ...@@ -2486,6 +2488,22 @@ add_pending_template (pt)
p->id = 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. */ /* called from the parser. */
void void
do_function_instantiation (declspecs, declarator, storage) do_function_instantiation (declspecs, declarator, storage)
...@@ -2495,10 +2513,17 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2495,10 +2513,17 @@ do_function_instantiation (declspecs, declarator, storage)
tree name = DECL_NAME (decl); tree name = DECL_NAME (decl);
tree fn = IDENTIFIER_GLOBAL_VALUE (name); tree fn = IDENTIFIER_GLOBAL_VALUE (name);
tree result = NULL_TREE; tree result = NULL_TREE;
int extern_p = 0;
if (fn) if (fn)
{ {
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (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)); int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
tree *targs = (tree *) malloc (sizeof (tree) * ntparms); tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
...@@ -2518,28 +2543,41 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2518,28 +2543,41 @@ do_function_instantiation (declspecs, declarator, storage)
} }
} }
if (! result) 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) if (flag_external_templates)
return; return;
SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
if (storage == NULL_TREE) 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 else
cp_error ("storage class `%D' applied to template instantiation", cp_error ("storage class `%D' applied to template instantiation",
storage); storage);
mark_function_instantiated (result, extern_p);
} }
void 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) do_type_instantiation (name, storage)
tree name, storage; tree name, storage;
{ {
...@@ -2578,18 +2616,7 @@ do_type_instantiation (name, storage) ...@@ -2578,18 +2616,7 @@ do_type_instantiation (name, storage)
} }
if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t)) if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
{ mark_class_instantiated (t, 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);
}
}
{ {
tree tmp; tree tmp;
...@@ -2615,8 +2642,7 @@ do_type_instantiation (name, storage) ...@@ -2615,8 +2642,7 @@ do_type_instantiation (name, storage)
if (! extern_p) if (! extern_p)
{ {
DECL_INTERFACE_KNOWN (tmp) = 1; DECL_INTERFACE_KNOWN (tmp) = 1;
DECL_EXTERNAL (tmp) = 0; DECL_NOT_REALLY_EXTERN (tmp) = 1;
TREE_STATIC (tmp) = 1;
} }
} }
......
/* 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);
}
...@@ -793,6 +793,10 @@ compute_access (basetype_path, field) ...@@ -793,6 +793,10 @@ compute_access (basetype_path, field)
} }
#endif #endif
/* We don't currently support access control on nested types. */
if (TREE_CODE (field) == TYPE_DECL)
return access_public;
previous_scope = current_scope (); previous_scope = current_scope ();
context = DECL_CLASS_CONTEXT (field); context = DECL_CLASS_CONTEXT (field);
......
...@@ -2880,7 +2880,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -2880,7 +2880,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree build_type = 0; tree build_type = 0;
/* Nonzero means after finally constructing the expression /* 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; tree final_type = 0;
/* Nonzero if this is an operation like MIN or MAX which can /* 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) ...@@ -3155,34 +3155,39 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else else
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1); type0, type1);
if (result_type == NULL_TREE)
result_type = ptr_type_node;
} }
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1)) && integer_zerop (op1))
op1 = null_pointer_node; result_type = type0;
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0)) && integer_zerop (op0))
op0 = null_pointer_node; result_type = type1;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{ {
result_type = type0;
error ("ANSI C++ forbids comparison between pointer and integer"); error ("ANSI C++ forbids comparison between pointer and integer");
op1 = convert (TREE_TYPE (op0), op1);
} }
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{ {
result_type = type1;
error ("ANSI C++ forbids comparison between pointer and integer"); 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 else if (TYPE_PTRMEMFUNC_P (type0) && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1)) && integer_zerop (op1))
{ {
op0 = build_component_ref (op0, index_identifier, 0, 0); op0 = build_component_ref (op0, index_identifier, 0, 0);
op1 = integer_zero_node; op1 = integer_zero_node;
result_type = TREE_TYPE (op0);
} }
else if (TYPE_PTRMEMFUNC_P (type1) && TREE_CODE (op0) == INTEGER_CST else if (TYPE_PTRMEMFUNC_P (type1) && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0)) && integer_zerop (op0))
{ {
op0 = build_component_ref (op1, index_identifier, 0, 0); op0 = build_component_ref (op1, index_identifier, 0, 0);
op1 = integer_zero_node; op1 = integer_zero_node;
result_type = TREE_TYPE (op0);
} }
else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1) else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1)
&& (TYPE_PTRMEMFUNC_FN_TYPE (type0) && (TYPE_PTRMEMFUNC_FN_TYPE (type0)
...@@ -3258,11 +3263,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3258,11 +3263,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
{ {
return build_binary_op (code, op1, op0, 1); 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; break;
case MAX_EXPR: case MAX_EXPR:
...@@ -3272,29 +3272,15 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3272,29 +3272,15 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
shorten = 1; shorten = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) 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", cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1); type0, type1);
result_type = ptr_type_node; 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; break;
case LE_EXPR: case LE_EXPR:
...@@ -3307,50 +3293,37 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3307,50 +3293,37 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
short_compare = 1; short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) 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", cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1); type0, type1);
#if 0 result_type = ptr_type_node;
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);
} }
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1)) && integer_zerop (op1))
op1 = null_pointer_node; result_type = type0;
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0)) && integer_zerop (op0))
op0 = null_pointer_node; result_type = type1;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{ {
result_type = type0;
if (pedantic) if (pedantic)
pedwarn ("ANSI C++ forbids comparison between pointer and integer"); pedwarn ("ANSI C++ forbids comparison between pointer and integer");
else if (! flag_traditional) else if (! flag_traditional)
warning ("comparison between pointer and integer"); warning ("comparison between pointer and integer");
op1 = convert (TREE_TYPE (op0), op1);
} }
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{ {
result_type = type1;
if (pedantic) if (pedantic)
pedwarn ("ANSI C++ forbids comparison between pointer and integer"); pedwarn ("ANSI C++ forbids comparison between pointer and integer");
else if (! flag_traditional) else if (! flag_traditional)
warning ("comparison between pointer and integer"); 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; break;
} }
...@@ -3496,26 +3469,38 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -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 op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1)); int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
tree comp_type = TREE_TYPE (op0);
int unsignedp0, unsignedp1; int unsignedp0, unsignedp1;
tree primop0 = get_narrower (op0, &unsignedp0); tree primop0 = get_narrower (op0, &unsignedp0);
tree primop1 = get_narrower (op1, &unsignedp1); tree primop1 = get_narrower (op1, &unsignedp1);
/* Give warnings for comparisons between signed and unsigned /* Give warnings for comparisons between signed and unsigned
quantities that may fail. Do not warn if the signed quantity quantities that may fail. */
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. */
/* Do the checking based on the original operand trees, so that /* Do the checking based on the original operand trees, so that
casts will be considered, but default promotions won't be. */ casts will be considered, but default promotions won't be. */
if (TREE_UNSIGNED (comp_type)
&& ((op0_signed && (TREE_CODE (orig_op0) != INTEGER_CST /* Do not warn if the comparison is being done in a signed type,
|| tree_int_cst_sgn (orig_op0) == -1)) since the signed type will only be chosen if it can represent
|| (op1_signed && (TREE_CODE (orig_op1) != INTEGER_CST all the values of the unsigned type. */
|| tree_int_cst_sgn (orig_op1) == -1)))) 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"); warning ("comparison between signed and unsigned");
/* Warn if two unsigned values are being compared in a size /* Warn if two unsigned values are being compared in a size
...@@ -3526,7 +3511,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3526,7 +3511,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
have all bits set that are set in the ~ operand when it is have all bits set that are set in the ~ operand when it is
extended. */ extended. */
else if (TREE_CODE (primop0) == BIT_NOT_EXPR if (TREE_CODE (primop0) == BIT_NOT_EXPR
^ TREE_CODE (primop1) == BIT_NOT_EXPR) ^ TREE_CODE (primop1) == BIT_NOT_EXPR)
{ {
if (TREE_CODE (primop0) == BIT_NOT_EXPR) if (TREE_CODE (primop0) == BIT_NOT_EXPR)
...@@ -3556,7 +3541,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3556,7 +3541,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
} }
bits = TYPE_PRECISION (TREE_TYPE (primop)); bits = TYPE_PRECISION (TREE_TYPE (primop));
if (bits < TYPE_PRECISION (comp_type) if (bits < TYPE_PRECISION (result_type)
&& bits < HOST_BITS_PER_LONG && unsignedp) && bits < HOST_BITS_PER_LONG && unsignedp)
{ {
mask = (~ (HOST_WIDE_INT) 0) << bits; mask = (~ (HOST_WIDE_INT) 0) << bits;
...@@ -3566,9 +3551,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3566,9 +3551,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
} }
else if (unsignedp0 && unsignedp1 else if (unsignedp0 && unsignedp1
&& (TYPE_PRECISION (TREE_TYPE (primop0)) && (TYPE_PRECISION (TREE_TYPE (primop0))
< TYPE_PRECISION (comp_type)) < TYPE_PRECISION (result_type))
&& (TYPE_PRECISION (TREE_TYPE (primop1)) && (TYPE_PRECISION (TREE_TYPE (primop1))
< TYPE_PRECISION (comp_type))) < TYPE_PRECISION (result_type)))
warning ("comparison of promoted ~unsigned with unsigned"); warning ("comparison of promoted ~unsigned with unsigned");
} }
} }
...@@ -3582,7 +3567,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3582,7 +3567,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (!result_type) 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; return error_mark_node;
} }
...@@ -4467,7 +4453,7 @@ mark_addressable (exp) ...@@ -4467,7 +4453,7 @@ mark_addressable (exp)
be non-zero in the case of processing a default function. be non-zero in the case of processing a default function.
The second may be non-zero in the case of a template function. */ The second may be non-zero in the case of a template function. */
x = DECL_MAIN_VARIANT (x); 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 && (DECL_CONTEXT (x) == NULL_TREE
|| TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't' || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't'
|| ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x)))) || ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x))))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment