+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.
$(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
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
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)
\f
# These exist for maintenance purposes.
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
{
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;
#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))
/* 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)
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),
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;
= "`%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. */
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
}
}
- /* 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);
/* 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)
/* 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";
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)
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;
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)
}
/* 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))
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;
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 */
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
{
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)
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;
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. */
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
/* 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.
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);
}
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
int returns_value;
int returns_null;
int warn_about_return_type;
- int extern_inline;
int assigns_this;
int just_assigned_this;
int parms_stored;
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;
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;
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. */
{"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.
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);
}
}
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;
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;
}
}
}
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);
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;
assemble_constructor (IDENTIFIER_POINTER (fnname));
}
+ permanent_allocation (1);
+
/* Done with C language context needs. */
pop_lang_context ();
{
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);
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;
}
}
}
- permanent_allocation (1);
+ finish_repo ();
+
this_time = get_run_time ();
parse_time -= this_time - start_time;
varconst_time += this_time - start_time;
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);
}
}
+/* 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
{
rtx false_label_rtx;
rtx protect_label_rtx;
- tree type;
- tree decl;
+ tree decl = NULL_TREE;
tree init;
if (! doing_eh (1))
/* 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 ();
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;
-
- typestring = build_overload_name (type, 1, 1);
-
- 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);
+ tree init_type;
+
+ decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
+
+ 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
tree exp;
{
rtx label;
- tree type;
if (! doing_eh (1))
return;
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, type, build_tree_list (NULL_TREE, exp), 0);
-
- 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);
- }
+ /* 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);
+
+ if (exp == error_mark_node)
+ 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);
+ emit_move_insn (saved_throw_value, throw_value_rtx);
+ emit_move_insn (saved_throw_type, throw_type_rtx);
}
else
{
{
e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1;
+ TREE_USED (e) = 1;
}
return e;
}
if (flag_cadillac)
cadillac_start ();
if (flag_gnu_xref) GNU_xref_begin (input_filename);
+ init_repo (input_filename);
}
void
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)
{
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.
= 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 ();
}
pop_obstacks ();
end_template_instantiation ($1);
+ repo_template_used (t);
+
/* Now go after the methods & class data. */
instantiate_member_templates ($1);
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();
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;
DECIDE (0);
if (DECL_EXPLICIT_INSTANTIATION (t))
- DECIDE (! DECL_EXTERNAL (t));
+ DECIDE (DECL_NOT_REALLY_EXTERN (t));
else if (! flag_implicit_templates)
DECIDE (0);
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)
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);
}
}
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;
}
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;
if (! extern_p)
{
DECL_INTERFACE_KNOWN (tmp) = 1;
- DECL_EXTERNAL (tmp) = 0;
- TREE_STATIC (tmp) = 1;
+ DECL_NOT_REALLY_EXTERN (tmp) = 1;
}
}
--- /dev/null
+/* 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);
+}
}
#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);
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
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)
{
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:
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:
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;
}
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
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);
}
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;
}
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");
}
}
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;
}
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))))