parent
684cfb6b2f
commit
faae18abc2
113
gcc/cp/ChangeLog
113
gcc/cp/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
218
gcc/cp/decl.c
218
gcc/cp/decl.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
148
gcc/cp/except.c
148
gcc/cp/except.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
78
gcc/cp/pt.c
78
gcc/cp/pt.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
128
gcc/cp/typeck.c
128
gcc/cp/typeck.c
|
@ -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))))
|
||||
|
|
Loading…
Reference in New Issue