Move statement-tree facilities from C++ to C front-end.
* c-common.h (c_tree_index): Add CTI_VOID_ZERO. (void_zero_node): New macro. (struct stmt_tree_s): New type. (stmt_tree): New typedef. (struct language_function): New type. (last_tree): New macro. (last_expr_type): Likewise. (walk_tree_fn): New typedef. (current_stmt_tree): New function. (begin_stmt_tree): Likewise. (add_stmt): Likewise. (finish_stmt_tree): Likewise. (statement_code_p): Likewise. (lang_statement_code_p): New variable. (walk_stmt_tree): New function. (STMT_IS_FULL_EXPR_P): New macro. * c-common.c (lang_statement_code_p): New variable. (c_common_nodes_and_builtins): Initialize void_zero_node. (statement_code_p): New function. (walk_stmt_tree): Likewise. * c-decl.c (language_function): Rename to ... (c_language_function): ... this. Include language_function. (push_c_function_context): Adjust accordingly. (pop_c_function_context): Likewise. (mark_c_function_context): Likewise. (current_stmt_tree): Define. * c-semantics.c (begin_stmt_tree): New function. (add_stmt): Likewise. (prune_unused_decls): Likewise. (finish_stmt_tree): Likewise. Move statement-tree facilities from C++ to C front-end. * cp-tree.h (cp_tree_index): Remove CPTI_VOID_ZERO. (void_zero_node): Remove. (stmt_tree): Likewise. (scope_chain): Adjust. (language_function): Rename to cp_language_function. (cp_function_chain): Adjust. (current_stmt_tree): Remove. (last_tree): Likewise. (last_expr_type): Likewise. (struct lang_decl): Adjust. (STMT_IS_FULL_EXPR_P): Remove. (add_tree): Remove. (begin_stmt_tree): Likewise. (finish_stmt_tree): Likewise. (walk_tree_fn): Likewise. (walk_stmt_tree): Likewise. * class.c (finish_struct): Replace use of add_tree with add_stmt. * decl.c (mark_stmt_tree): Adjust type. (init_decl_processing): Don't build void_zero_node. (initialize_local_var): Adjust usage of current_stmt_tree. (finish_enum): Use add_stmt, not add_tree. (save_function_data): Adjust use of language_function. (finish_constructor_body): Use add_stmt, not add_tree. (finish_destructor_body): Likewise. (push_cp_function_context): Adjust use of language_function. (pop_cp_function_context): Likewise. (mark_lang_function): Likewise. (mark_cp_function_context): Likewise. * init.c (build_aggr_init): Adjust use of current_stmt_tree. (build_vec_init): Likewise. * semantics.c (SET_LAST_STMT): Remove. (RECHAIN_STMTS): Don't use it. (stmts_are_full_exprs_p): Adjust use of current_stmt_tree. (current_stmt_tree): Define. (add_tree): Remove. (finish_goto_stmt): Use add_stmt, not add_tree. (finish_expr_stmt): Likewise. (begin_if_stmt): Likewise. (finish_then_clause): Likewise. (begin_while_stmt): Likewise. (begin_do_stmt): Likewise. (finish_return_stmt): Likewise. (begin_for_stmt): Likewise. (finish_break_stmt): Likewise. (finish_continue_stmt): Likewise. (begin_switch_stmt): Likewise. (finish_case_label): Likewise. (begin_try_block): Likewise. (begin_function_try_block): Likewise. (begin_handler): Likewise. (begin_catch_block): Likewise. (begin_compound_stmt): Likewise. (begin_asm_stmt): Likewise. (finish_asm_stmt): Likewise. (finish_label_stmt): Likewise. (add_decl_stmt): Likewise. (finish_subobject): Likewise. (finish_decl_cleanup): Likewise. (finish_named_return_value): Likewise. (setup_vtbl_ptr): Likewise. (add_scope_stmt): Likewise. (finish_stmt_expr): Likewise. (prune_unused_decls): Remove. (begin_stmt_tree): Likewise. (finish_stmt_tree): Likewise. (prep_stmt): Adjust use of current_stmt_tree. (lang_expand_stmt): Likewise. * tree.c (statement_code_p): Remove. (cp_statement_code_p): New function. (walk_stmt_tree): Remove. (init_tree): Set lang_statement_code_p. From-SVN: r36221
This commit is contained in:
parent
4f4b88d083
commit
ae499ccea4
@ -1,3 +1,37 @@
|
||||
2000-09-06 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
Move statement-tree facilities from C++ to C front-end.
|
||||
* c-common.h (c_tree_index): Add CTI_VOID_ZERO.
|
||||
(void_zero_node): New macro.
|
||||
(struct stmt_tree_s): New type.
|
||||
(stmt_tree): New typedef.
|
||||
(struct language_function): New type.
|
||||
(last_tree): New macro.
|
||||
(last_expr_type): Likewise.
|
||||
(walk_tree_fn): New typedef.
|
||||
(current_stmt_tree): New function.
|
||||
(begin_stmt_tree): Likewise.
|
||||
(add_stmt): Likewise.
|
||||
(finish_stmt_tree): Likewise.
|
||||
(statement_code_p): Likewise.
|
||||
(lang_statement_code_p): New variable.
|
||||
(walk_stmt_tree): New function.
|
||||
(STMT_IS_FULL_EXPR_P): New macro.
|
||||
* c-common.c (lang_statement_code_p): New variable.
|
||||
(c_common_nodes_and_builtins): Initialize void_zero_node.
|
||||
(statement_code_p): New function.
|
||||
(walk_stmt_tree): Likewise.
|
||||
* c-decl.c (language_function): Rename to ...
|
||||
(c_language_function): ... this. Include language_function.
|
||||
(push_c_function_context): Adjust accordingly.
|
||||
(pop_c_function_context): Likewise.
|
||||
(mark_c_function_context): Likewise.
|
||||
(current_stmt_tree): Define.
|
||||
* c-semantics.c (begin_stmt_tree): New function.
|
||||
(add_stmt): Likewise.
|
||||
(prune_unused_decls): Likewise.
|
||||
(finish_stmt_tree): Likewise.
|
||||
|
||||
2000-09-06 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
|
||||
|
||||
* flow.c (insn_dead_p): Detect dead memory stores with auto increments.
|
||||
|
112
gcc/c-common.c
112
gcc/c-common.c
@ -144,6 +144,10 @@ tree *ridpointers;
|
||||
|
||||
tree (*make_fname_decl) PARAMS ((tree, const char *, int));
|
||||
|
||||
/* If non-NULL, the address of a language-specific function that
|
||||
returns 1 for language-specific statement codes. */
|
||||
int (*lang_statement_code_p) PARAMS ((enum tree_code));
|
||||
|
||||
/* Nonzero means the expression being parsed will never be evaluated.
|
||||
This is a count, since unevaluated expressions can nest. */
|
||||
int skip_evaluation;
|
||||
@ -3870,6 +3874,9 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
|
||||
sizetype,
|
||||
endlink))));
|
||||
|
||||
void_zero_node = build_int_2 (0, 0);
|
||||
TREE_TYPE (void_zero_node) = void_type_node;
|
||||
|
||||
/* Prototype for strcpy. */
|
||||
string_ftype_ptr_ptr
|
||||
= build_function_type (string_type_node,
|
||||
@ -4378,6 +4385,111 @@ expand_tree_builtin (function, params, coerced_params)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Returns non-zero if CODE is the code for a statement. */
|
||||
|
||||
int
|
||||
statement_code_p (code)
|
||||
enum tree_code code;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case EXPR_STMT:
|
||||
case COMPOUND_STMT:
|
||||
case DECL_STMT:
|
||||
case IF_STMT:
|
||||
case FOR_STMT:
|
||||
case WHILE_STMT:
|
||||
case DO_STMT:
|
||||
case RETURN_STMT:
|
||||
case BREAK_STMT:
|
||||
case CONTINUE_STMT:
|
||||
case SWITCH_STMT:
|
||||
case GOTO_STMT:
|
||||
case LABEL_STMT:
|
||||
case ASM_STMT:
|
||||
case CASE_LABEL:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
if (lang_statement_code_p)
|
||||
return (*lang_statement_code_p) (code);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk the statemen tree, rooted at *tp. Apply FUNC to all the
|
||||
sub-trees of *TP in a pre-order traversal. FUNC is called with the
|
||||
DATA and the address of each sub-tree. If FUNC returns a non-NULL
|
||||
value, the traversal is aborted, and the value returned by FUNC is
|
||||
returned. If FUNC sets WALK_SUBTREES to zero, then the subtrees of
|
||||
the node being visited are not walked.
|
||||
|
||||
We don't need a without_duplicates variant of this one because the
|
||||
statement tree is a tree, not a graph. */
|
||||
|
||||
tree
|
||||
walk_stmt_tree (tp, func, data)
|
||||
tree *tp;
|
||||
walk_tree_fn func;
|
||||
void *data;
|
||||
{
|
||||
enum tree_code code;
|
||||
int walk_subtrees;
|
||||
tree result;
|
||||
int i, len;
|
||||
|
||||
#define WALK_SUBTREE(NODE) \
|
||||
do \
|
||||
{ \
|
||||
result = walk_stmt_tree (&(NODE), func, data); \
|
||||
if (result) \
|
||||
return result; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Skip empty subtrees. */
|
||||
if (!*tp)
|
||||
return NULL_TREE;
|
||||
|
||||
/* Skip subtrees below non-statement nodes. */
|
||||
if (!statement_code_p (TREE_CODE (*tp)))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Call the function. */
|
||||
walk_subtrees = 1;
|
||||
result = (*func) (tp, &walk_subtrees, data);
|
||||
|
||||
/* If we found something, return it. */
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
/* Even if we didn't, FUNC may have decided that there was nothing
|
||||
interesting below this point in the tree. */
|
||||
if (!walk_subtrees)
|
||||
return NULL_TREE;
|
||||
|
||||
/* FUNC may have modified the tree, recheck that we're looking at a
|
||||
statement node. */
|
||||
code = TREE_CODE (*tp);
|
||||
if (!statement_code_p (code))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Walk over all the sub-trees of this operand. Statement nodes never
|
||||
contain RTL, and we needn't worry about TARGET_EXPRs. */
|
||||
len = TREE_CODE_LENGTH (code);
|
||||
|
||||
/* Go through the subtrees. We need to do this in forward order so
|
||||
that the scope of a FOR_EXPR is handled properly. */
|
||||
for (i = 0; i < len; ++i)
|
||||
WALK_SUBTREE (TREE_OPERAND (*tp, i));
|
||||
|
||||
/* Finally visit the chain. This can be tail-recursion optimized if
|
||||
we write it this way. */
|
||||
return walk_stmt_tree (&TREE_CHAIN (*tp), func, data);
|
||||
|
||||
#undef WALK_SUBTREE
|
||||
}
|
||||
|
||||
/* Tree code classes. */
|
||||
|
||||
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
|
||||
|
@ -147,6 +147,8 @@ enum c_tree_index
|
||||
CTI_PRETTY_FUNCTION_ID,
|
||||
CTI_FUNC_ID,
|
||||
|
||||
CTI_VOID_ZERO,
|
||||
|
||||
CTI_MAX
|
||||
};
|
||||
|
||||
@ -187,6 +189,9 @@ enum c_tree_index
|
||||
#define pretty_function_id_node c_global_trees[CTI_PRETTY_FUNCTION_ID]
|
||||
#define func_id_node c_global_trees[CTI_FUNC_ID]
|
||||
|
||||
/* A node for `((void) 0)'. */
|
||||
#define void_zero_node c_global_trees[CTI_VOID_ZERO]
|
||||
|
||||
extern tree c_global_trees[CTI_MAX];
|
||||
|
||||
typedef enum c_language_kind
|
||||
@ -198,6 +203,68 @@ typedef enum c_language_kind
|
||||
}
|
||||
c_language_kind;
|
||||
|
||||
/* Information about a statement tree. */
|
||||
|
||||
struct stmt_tree_s {
|
||||
/* The last statement added to the tree. */
|
||||
tree x_last_stmt;
|
||||
/* The type of the last expression statement. (This information is
|
||||
needed to implement the statement-expression extension.) */
|
||||
tree x_last_expr_type;
|
||||
/* In C++, Non-zero if we should treat statements as full
|
||||
expressions. In particular, this variable is no-zero if at the
|
||||
end of a statement we should destroy any temporaries created
|
||||
during that statement. Similarly, if, at the end of a block, we
|
||||
should destroy any local variables in this block. Normally, this
|
||||
variable is non-zero, since those are the normal semantics of
|
||||
C++.
|
||||
|
||||
However, in order to represent aggregate initialization code as
|
||||
tree structure, we use statement-expressions. The statements
|
||||
within the statement expression should not result in cleanups
|
||||
being run until the entire enclosing statement is complete.
|
||||
|
||||
This flag has no effect in C. */
|
||||
int stmts_are_full_exprs_p;
|
||||
};
|
||||
|
||||
typedef struct stmt_tree_s *stmt_tree;
|
||||
|
||||
/* Global state pertinent to the current function. Some C dialects
|
||||
extend this structure with additional fields. */
|
||||
|
||||
struct language_function {
|
||||
/* While we are parsing the function, this contains information
|
||||
about the statement-tree that we are building. */
|
||||
struct stmt_tree_s x_stmt_tree;
|
||||
};
|
||||
|
||||
/* When building a statement-tree, this is the last statement added to
|
||||
the tree. */
|
||||
|
||||
#define last_tree (current_stmt_tree ()->x_last_stmt)
|
||||
|
||||
/* The type of the last expression-statement we have seen. */
|
||||
|
||||
#define last_expr_type (current_stmt_tree ()->x_last_expr_type)
|
||||
|
||||
/* The type of a function that walks over tree structure. */
|
||||
|
||||
typedef tree (*walk_tree_fn) PARAMS ((tree *,
|
||||
int *,
|
||||
void *));
|
||||
|
||||
extern stmt_tree current_stmt_tree PARAMS ((void));
|
||||
extern void begin_stmt_tree PARAMS ((tree *));
|
||||
extern void add_stmt PARAMS ((tree));
|
||||
extern void finish_stmt_tree PARAMS ((tree *));
|
||||
|
||||
extern int statement_code_p PARAMS ((enum tree_code));
|
||||
extern int (*lang_statement_code_p) PARAMS ((enum tree_code));
|
||||
extern tree walk_stmt_tree PARAMS ((tree *,
|
||||
walk_tree_fn,
|
||||
void *));
|
||||
|
||||
/* The variant of the C language being processed. Each C language
|
||||
front-end defines this variable. */
|
||||
|
||||
@ -337,8 +404,13 @@ extern tree build_va_arg PARAMS ((tree, tree));
|
||||
extern int self_promoting_args_p PARAMS ((tree));
|
||||
extern tree simple_type_promotes_to PARAMS ((tree));
|
||||
|
||||
/* These macros provide convenient access to the various _STMT nodes
|
||||
created when parsing template declarations. */
|
||||
/* These macros provide convenient access to the various _STMT nodes. */
|
||||
|
||||
/* Nonzero if this statement should be considered a full-expression,
|
||||
i.e., if temporaries created during this statement should have
|
||||
their destructors run at the end of this statement. (In C, this
|
||||
will always be false, since there are no destructors.) */
|
||||
#define STMT_IS_FULL_EXPR_P(NODE) TREE_LANG_FLAG_1 ((NODE))
|
||||
|
||||
/* IF_STMT accessors. These give access to the condtion of the if
|
||||
statement, the then block of the if statement, and the else block
|
||||
|
26
gcc/c-decl.c
26
gcc/c-decl.c
@ -6761,8 +6761,9 @@ finish_function (nested)
|
||||
that keep track of the progress of compilation of the current function.
|
||||
Used for nested functions. */
|
||||
|
||||
struct language_function
|
||||
struct c_language_function
|
||||
{
|
||||
struct language_function base;
|
||||
tree named_labels;
|
||||
tree shadowed_labels;
|
||||
int returns_value;
|
||||
@ -6779,9 +6780,10 @@ void
|
||||
push_c_function_context (f)
|
||||
struct function *f;
|
||||
{
|
||||
struct language_function *p;
|
||||
p = (struct language_function *) xmalloc (sizeof (struct language_function));
|
||||
f->language = p;
|
||||
struct c_language_function *p;
|
||||
p = ((struct c_language_function *)
|
||||
xmalloc (sizeof (struct c_language_function)));
|
||||
f->language = (struct language_function *) p;
|
||||
|
||||
p->named_labels = named_labels;
|
||||
p->shadowed_labels = shadowed_labels;
|
||||
@ -6798,7 +6800,8 @@ void
|
||||
pop_c_function_context (f)
|
||||
struct function *f;
|
||||
{
|
||||
struct language_function *p = f->language;
|
||||
struct c_language_function *p
|
||||
= (struct c_language_function *) f->language;
|
||||
tree link;
|
||||
|
||||
/* Bring back all the labels that were shadowed. */
|
||||
@ -6834,7 +6837,8 @@ void
|
||||
mark_c_function_context (f)
|
||||
struct function *f;
|
||||
{
|
||||
struct language_function *p = f->language;
|
||||
struct c_language_function *p
|
||||
= (struct c_language_function *) f->language;
|
||||
|
||||
if (p == 0)
|
||||
return;
|
||||
@ -6899,6 +6903,16 @@ stmts_are_full_exprs_p ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the stmt_tree (if any) to which statements are currently
|
||||
being added. If there is no active statement-tree, NULL is
|
||||
returned. */
|
||||
|
||||
stmt_tree
|
||||
current_stmt_tree ()
|
||||
{
|
||||
return cfun ? &cfun->language->x_stmt_tree : NULL;
|
||||
}
|
||||
|
||||
/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
|
||||
C. */
|
||||
|
||||
|
@ -36,6 +36,119 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "output.h"
|
||||
#include "timevar.h"
|
||||
|
||||
static tree prune_unused_decls PARAMS ((tree *, int *, void *));
|
||||
|
||||
/* Create an empty statement tree rooted at T. */
|
||||
|
||||
void
|
||||
begin_stmt_tree (t)
|
||||
tree *t;
|
||||
{
|
||||
/* We create a trivial EXPR_STMT so that last_tree is never NULL in
|
||||
what follows. We remove the extraneous statement in
|
||||
finish_stmt_tree. */
|
||||
*t = build_nt (EXPR_STMT, void_zero_node);
|
||||
last_tree = *t;
|
||||
last_expr_type = NULL_TREE;
|
||||
}
|
||||
|
||||
/* T is a statement. Add it to the statement-tree. */
|
||||
|
||||
void
|
||||
add_stmt (t)
|
||||
tree t;
|
||||
{
|
||||
/* Add T to the statement-tree. */
|
||||
TREE_CHAIN (last_tree) = t;
|
||||
last_tree = t;
|
||||
/* When we expand a statement-tree, we must know whether or not the
|
||||
statements are full-expresions. We record that fact here. */
|
||||
STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
|
||||
}
|
||||
|
||||
/* Remove declarations of internal variables that are not used from a
|
||||
stmt tree. To qualify, the variable must have a name and must have
|
||||
a zero DECL_SOURCE_LINE. We tried to remove all variables for
|
||||
which TREE_USED was false, but it turns out that there's tons of
|
||||
variables for which TREE_USED is false but that are still in fact
|
||||
used. */
|
||||
|
||||
static tree
|
||||
prune_unused_decls (tp, walk_subtrees, data)
|
||||
tree *tp;
|
||||
int *walk_subtrees ATTRIBUTE_UNUSED;
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
tree t = *tp;
|
||||
|
||||
if (t == NULL_TREE)
|
||||
{
|
||||
*walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (TREE_CODE (t) == DECL_STMT)
|
||||
{
|
||||
tree d = DECL_STMT_DECL (t);
|
||||
if (!TREE_USED (d) && DECL_NAME (d) && DECL_SOURCE_LINE (d) == 0)
|
||||
{
|
||||
*tp = TREE_CHAIN (t);
|
||||
/* Recurse on the new value of tp, otherwise we will skip
|
||||
the next statement. */
|
||||
return prune_unused_decls (tp, walk_subtrees, data);
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (t) == SCOPE_STMT)
|
||||
{
|
||||
/* Remove all unused decls from the BLOCK of this SCOPE_STMT. */
|
||||
tree block = SCOPE_STMT_BLOCK (t);
|
||||
|
||||
if (block)
|
||||
{
|
||||
tree *vp;
|
||||
|
||||
for (vp = &BLOCK_VARS (block); *vp; )
|
||||
{
|
||||
tree v = *vp;
|
||||
if (! TREE_USED (v) && DECL_NAME (v) && DECL_SOURCE_LINE (v) == 0)
|
||||
*vp = TREE_CHAIN (v); /* drop */
|
||||
else
|
||||
vp = &TREE_CHAIN (v); /* advance */
|
||||
}
|
||||
/* If there are now no variables, the entire BLOCK can be dropped.
|
||||
(This causes SCOPE_NULLIFIED_P (t) to be true.) */
|
||||
if (BLOCK_VARS (block) == NULL_TREE)
|
||||
SCOPE_STMT_BLOCK (t) = NULL_TREE;
|
||||
}
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Finish the statement tree rooted at T. */
|
||||
|
||||
void
|
||||
finish_stmt_tree (t)
|
||||
tree *t;
|
||||
{
|
||||
tree stmt;
|
||||
|
||||
/* Remove the fake extra statement added in begin_stmt_tree. */
|
||||
stmt = TREE_CHAIN (*t);
|
||||
*t = stmt;
|
||||
last_tree = NULL_TREE;
|
||||
|
||||
/* Remove unused decls from the stmt tree. */
|
||||
walk_stmt_tree (t, prune_unused_decls, NULL);
|
||||
|
||||
if (cfun)
|
||||
{
|
||||
/* The line-number recorded in the outermost statement in a function
|
||||
is the line number of the end of the function. */
|
||||
STMT_LINENO (stmt) = lineno;
|
||||
STMT_LINENO_FOR_FN_P (stmt) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build a generic statement based on the given type of node and
|
||||
arguments. Similar to `build_nt', except that we set
|
||||
TREE_COMPLEXITY to be the current line number. */
|
||||
|
@ -1,3 +1,78 @@
|
||||
2000-09-06 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
Move statement-tree facilities from C++ to C front-end.
|
||||
* cp-tree.h (cp_tree_index): Remove CPTI_VOID_ZERO.
|
||||
(void_zero_node): Remove.
|
||||
(stmt_tree): Likewise.
|
||||
(scope_chain): Adjust.
|
||||
(language_function): Rename to cp_language_function.
|
||||
(cp_function_chain): Adjust.
|
||||
(current_stmt_tree): Remove.
|
||||
(last_tree): Likewise.
|
||||
(last_expr_type): Likewise.
|
||||
(struct lang_decl): Adjust.
|
||||
(STMT_IS_FULL_EXPR_P): Remove.
|
||||
(add_tree): Remove.
|
||||
(begin_stmt_tree): Likewise.
|
||||
(finish_stmt_tree): Likewise.
|
||||
(walk_tree_fn): Likewise.
|
||||
(walk_stmt_tree): Likewise.
|
||||
* class.c (finish_struct): Replace use of add_tree with add_stmt.
|
||||
* decl.c (mark_stmt_tree): Adjust type.
|
||||
(init_decl_processing): Don't build void_zero_node.
|
||||
(initialize_local_var): Adjust usage of current_stmt_tree.
|
||||
(finish_enum): Use add_stmt, not add_tree.
|
||||
(save_function_data): Adjust use of language_function.
|
||||
(finish_constructor_body): Use add_stmt, not add_tree.
|
||||
(finish_destructor_body): Likewise.
|
||||
(push_cp_function_context): Adjust use of language_function.
|
||||
(pop_cp_function_context): Likewise.
|
||||
(mark_lang_function): Likewise.
|
||||
(mark_cp_function_context): Likewise.
|
||||
* init.c (build_aggr_init): Adjust use of current_stmt_tree.
|
||||
(build_vec_init): Likewise.
|
||||
* semantics.c (SET_LAST_STMT): Remove.
|
||||
(RECHAIN_STMTS): Don't use it.
|
||||
(stmts_are_full_exprs_p): Adjust use of current_stmt_tree.
|
||||
(current_stmt_tree): Define.
|
||||
(add_tree): Remove.
|
||||
(finish_goto_stmt): Use add_stmt, not add_tree.
|
||||
(finish_expr_stmt): Likewise.
|
||||
(begin_if_stmt): Likewise.
|
||||
(finish_then_clause): Likewise.
|
||||
(begin_while_stmt): Likewise.
|
||||
(begin_do_stmt): Likewise.
|
||||
(finish_return_stmt): Likewise.
|
||||
(begin_for_stmt): Likewise.
|
||||
(finish_break_stmt): Likewise.
|
||||
(finish_continue_stmt): Likewise.
|
||||
(begin_switch_stmt): Likewise.
|
||||
(finish_case_label): Likewise.
|
||||
(begin_try_block): Likewise.
|
||||
(begin_function_try_block): Likewise.
|
||||
(begin_handler): Likewise.
|
||||
(begin_catch_block): Likewise.
|
||||
(begin_compound_stmt): Likewise.
|
||||
(begin_asm_stmt): Likewise.
|
||||
(finish_asm_stmt): Likewise.
|
||||
(finish_label_stmt): Likewise.
|
||||
(add_decl_stmt): Likewise.
|
||||
(finish_subobject): Likewise.
|
||||
(finish_decl_cleanup): Likewise.
|
||||
(finish_named_return_value): Likewise.
|
||||
(setup_vtbl_ptr): Likewise.
|
||||
(add_scope_stmt): Likewise.
|
||||
(finish_stmt_expr): Likewise.
|
||||
(prune_unused_decls): Remove.
|
||||
(begin_stmt_tree): Likewise.
|
||||
(finish_stmt_tree): Likewise.
|
||||
(prep_stmt): Adjust use of current_stmt_tree.
|
||||
(lang_expand_stmt): Likewise.
|
||||
* tree.c (statement_code_p): Remove.
|
||||
(cp_statement_code_p): New function.
|
||||
(walk_stmt_tree): Remove.
|
||||
(init_tree): Set lang_statement_code_p.
|
||||
|
||||
2000-09-06 Zack Weinberg <zack@wolery.cumb.org>
|
||||
|
||||
Integrated preprocessor.
|
||||
|
@ -5265,7 +5265,7 @@ finish_struct (t, attributes)
|
||||
{
|
||||
tree scope = current_scope ();
|
||||
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
|
||||
add_tree (build_min (TAG_DEFN, t));
|
||||
add_stmt (build_min (TAG_DEFN, t));
|
||||
}
|
||||
|
||||
return t;
|
||||
|
@ -559,7 +559,6 @@ enum cp_tree_index
|
||||
CPTI_JAVA_CHAR_TYPE,
|
||||
CPTI_JAVA_BOOLEAN_TYPE,
|
||||
|
||||
CPTI_VOID_ZERO,
|
||||
CPTI_WCHAR_DECL,
|
||||
CPTI_VTABLE_ENTRY_TYPE,
|
||||
CPTI_DELTA_TYPE,
|
||||
@ -652,7 +651,6 @@ extern tree cp_global_trees[CPTI_MAX];
|
||||
#define java_char_type_node cp_global_trees[CPTI_JAVA_CHAR_TYPE]
|
||||
#define java_boolean_type_node cp_global_trees[CPTI_JAVA_BOOLEAN_TYPE]
|
||||
|
||||
#define void_zero_node cp_global_trees[CPTI_VOID_ZERO]
|
||||
#define wchar_decl_node cp_global_trees[CPTI_WCHAR_DECL]
|
||||
#define vtable_entry_type cp_global_trees[CPTI_VTABLE_ENTRY_TYPE]
|
||||
/* The type used to represent an offset by which to adjust the `this'
|
||||
@ -784,23 +782,6 @@ extern tree cp_global_trees[CPTI_MAX];
|
||||
|
||||
/* Global state. */
|
||||
|
||||
struct stmt_tree {
|
||||
tree x_last_stmt;
|
||||
tree x_last_expr_type;
|
||||
/* Non-zero if we should treat statements as full expressions. In
|
||||
particular, this variable is no-zero if at the end of a statement
|
||||
we should destroy any temporaries created during that statement.
|
||||
Similarly, if, at the end of a block, we should destroy any local
|
||||
variables in this block. Normally, this variable is non-zero,
|
||||
since those are the normal semantics of C++.
|
||||
|
||||
However, in order to represent aggregate initialization code as
|
||||
tree structure, we use statement-expressions. The statements
|
||||
within the statement expression should not result in cleanups being
|
||||
run until the entire enclosing statement is complete. */
|
||||
int stmts_are_full_exprs_p;
|
||||
};
|
||||
|
||||
struct saved_scope {
|
||||
tree old_bindings;
|
||||
tree old_namespace;
|
||||
@ -824,7 +805,7 @@ struct saved_scope {
|
||||
int x_processing_explicit_instantiation;
|
||||
int need_pop_function_context;
|
||||
|
||||
struct stmt_tree x_stmt_tree;
|
||||
struct stmt_tree_s x_stmt_tree;
|
||||
|
||||
struct binding_level *class_bindings;
|
||||
struct binding_level *bindings;
|
||||
@ -890,8 +871,10 @@ extern struct saved_scope *scope_chain;
|
||||
|
||||
/* Global state pertinent to the current function. */
|
||||
|
||||
struct language_function
|
||||
struct cp_language_function
|
||||
{
|
||||
struct language_function base;
|
||||
|
||||
tree x_ctor_label;
|
||||
tree x_dtor_label;
|
||||
tree x_current_class_ptr;
|
||||
@ -912,8 +895,6 @@ struct language_function
|
||||
int name_declared;
|
||||
int vtbls_set_up_p;
|
||||
|
||||
struct stmt_tree x_stmt_tree;
|
||||
|
||||
struct named_label_use_list *x_named_label_uses;
|
||||
struct named_label_list *x_named_labels;
|
||||
struct binding_level *bindings;
|
||||
@ -923,7 +904,8 @@ struct language_function
|
||||
|
||||
/* The current C++-specific per-function global variables. */
|
||||
|
||||
#define cp_function_chain (cfun->language)
|
||||
#define cp_function_chain \
|
||||
((struct cp_language_function *) (cfun->language))
|
||||
|
||||
/* In a destructor, the point at which all derived class destroying
|
||||
has been done, just before any base class destroying will be done. */
|
||||
@ -944,24 +926,6 @@ struct language_function
|
||||
#define current_class_ref \
|
||||
(cfun ? cp_function_chain->x_current_class_ref : NULL_TREE)
|
||||
|
||||
/* Information about the current statement tree. */
|
||||
|
||||
#define current_stmt_tree \
|
||||
(cfun \
|
||||
? &cp_function_chain->x_stmt_tree \
|
||||
: &scope_chain->x_stmt_tree)
|
||||
|
||||
/* When building a statement-tree, this is the last statement added to
|
||||
the tree. */
|
||||
|
||||
#define last_tree current_stmt_tree->x_last_stmt
|
||||
|
||||
/* The type of the last expression-statement we have seen. This is
|
||||
required because the type of a statement-expression is the type of
|
||||
the last expression statement. */
|
||||
|
||||
#define last_expr_type current_stmt_tree->x_last_expr_type
|
||||
|
||||
/* The TRY_BLOCK for the exception-specifiers for the current
|
||||
function, if any. */
|
||||
|
||||
@ -1927,7 +1891,7 @@ struct lang_decl
|
||||
{
|
||||
tree sorted_fields;
|
||||
struct unparsed_text *pending_inline_info;
|
||||
struct language_function *saved_language_function;
|
||||
struct cp_language_function *saved_language_function;
|
||||
} u;
|
||||
|
||||
union {
|
||||
@ -2474,9 +2438,6 @@ struct lang_decl
|
||||
#define AGGR_INIT_VIA_CTOR_P(NODE) \
|
||||
TREE_LANG_FLAG_0 (AGGR_INIT_EXPR_CHECK (NODE))
|
||||
|
||||
/* Nonzero if this statement should be considered a full-expression. */
|
||||
#define STMT_IS_FULL_EXPR_P(NODE) TREE_LANG_FLAG_1 ((NODE))
|
||||
|
||||
/* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a
|
||||
TEMPLATE_DECL. This macro determines whether or not a given class
|
||||
type is really a template type, as opposed to an instantiation or
|
||||
@ -4231,7 +4192,6 @@ extern void do_decl_instantiation PARAMS ((tree, tree, tree));
|
||||
extern void do_type_instantiation PARAMS ((tree, tree, int));
|
||||
extern tree instantiate_decl PARAMS ((tree, int));
|
||||
extern tree get_bindings PARAMS ((tree, tree, tree));
|
||||
extern void add_tree PARAMS ((tree));
|
||||
extern void add_maybe_template PARAMS ((tree, tree));
|
||||
extern void pop_tinst_level PARAMS ((void));
|
||||
extern int more_specialized_class PARAMS ((tree, tree));
|
||||
@ -4409,8 +4369,6 @@ extern void add_decl_stmt PARAMS ((tree));
|
||||
extern void finish_decl_cleanup PARAMS ((tree, tree));
|
||||
extern void finish_named_return_value PARAMS ((tree, tree));
|
||||
extern void expand_body PARAMS ((tree));
|
||||
extern void begin_stmt_tree PARAMS ((tree *));
|
||||
extern void finish_stmt_tree PARAMS ((tree *));
|
||||
extern void prep_stmt PARAMS ((tree));
|
||||
extern tree add_scope_stmt PARAMS ((int, int));
|
||||
extern void do_pushlevel PARAMS ((void));
|
||||
@ -4494,7 +4452,6 @@ extern void debug_binfo PARAMS ((tree));
|
||||
extern tree build_dummy_object PARAMS ((tree));
|
||||
extern tree maybe_dummy_object PARAMS ((tree, tree *));
|
||||
extern int is_dummy_object PARAMS ((tree));
|
||||
typedef tree (*walk_tree_fn) PARAMS ((tree *, int *, void *));
|
||||
extern tree walk_tree PARAMS ((tree *,
|
||||
walk_tree_fn,
|
||||
void *,
|
||||
@ -4502,9 +4459,6 @@ extern tree walk_tree PARAMS ((tree *,
|
||||
extern tree walk_tree_without_duplicates PARAMS ((tree *,
|
||||
walk_tree_fn,
|
||||
void *));
|
||||
extern tree walk_stmt_tree PARAMS ((tree *,
|
||||
walk_tree_fn,
|
||||
void *));
|
||||
extern tree copy_tree_r PARAMS ((tree *, int *, void *));
|
||||
extern int cp_valid_lang_attribute PARAMS ((tree, tree, tree, tree));
|
||||
extern tree make_ptrmem_cst PARAMS ((tree, tree));
|
||||
|
@ -169,8 +169,8 @@ static void mark_binding_level PARAMS ((void *));
|
||||
static void mark_named_label_lists PARAMS ((void *, void *));
|
||||
static void mark_cp_function_context PARAMS ((struct function *));
|
||||
static void mark_saved_scope PARAMS ((void *));
|
||||
static void mark_lang_function PARAMS ((struct language_function *));
|
||||
static void mark_stmt_tree PARAMS ((struct stmt_tree *));
|
||||
static void mark_lang_function PARAMS ((struct cp_language_function *));
|
||||
static void mark_stmt_tree PARAMS ((stmt_tree));
|
||||
static void save_function_data PARAMS ((tree));
|
||||
static void check_function_type PARAMS ((tree));
|
||||
static void destroy_local_var PARAMS ((tree));
|
||||
@ -200,7 +200,6 @@ tree error_mark_list;
|
||||
|
||||
C++ extensions
|
||||
tree wchar_decl_node;
|
||||
tree void_zero_node;
|
||||
|
||||
tree vtable_entry_type;
|
||||
tree delta_type_node;
|
||||
@ -2453,7 +2452,7 @@ struct saved_scope *scope_chain;
|
||||
|
||||
static void
|
||||
mark_stmt_tree (st)
|
||||
struct stmt_tree *st;
|
||||
stmt_tree st;
|
||||
{
|
||||
ggc_mark_tree (st->x_last_stmt);
|
||||
ggc_mark_tree (st->x_last_expr_type);
|
||||
@ -6471,10 +6470,6 @@ init_decl_processing ()
|
||||
void_list_node = build_tree_list (NULL_TREE, void_type_node);
|
||||
TREE_PARMLIST (void_list_node) = 1;
|
||||
|
||||
/* Used for expressions that do nothing, but are not errors. */
|
||||
void_zero_node = build_int_2 (0, 0);
|
||||
TREE_TYPE (void_zero_node) = void_type_node;
|
||||
|
||||
string_type_node = build_pointer_type (char_type_node);
|
||||
const_string_type_node
|
||||
= build_pointer_type (build_qualified_type (char_type_node,
|
||||
@ -7965,12 +7960,13 @@ initialize_local_var (decl, init, flags)
|
||||
emit_line_note (DECL_SOURCE_FILE (decl),
|
||||
DECL_SOURCE_LINE (decl));
|
||||
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
|
||||
current_stmt_tree->stmts_are_full_exprs_p = 1;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
|
||||
if (building_stmt_tree ())
|
||||
finish_expr_stmt (build_aggr_init (decl, init, flags));
|
||||
else
|
||||
genrtl_expr_stmt (build_aggr_init (decl, init, flags));
|
||||
current_stmt_tree->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p =
|
||||
saved_stmts_are_full_exprs_p;
|
||||
}
|
||||
|
||||
/* Set this to 0 so we can tell whether an aggregate which was
|
||||
@ -13244,7 +13240,7 @@ finish_enum (enumtype)
|
||||
{
|
||||
tree scope = current_scope ();
|
||||
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
|
||||
add_tree (build_min (TAG_DEFN, enumtype));
|
||||
add_stmt (build_min (TAG_DEFN, enumtype));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -14037,7 +14033,7 @@ static void
|
||||
save_function_data (decl)
|
||||
tree decl;
|
||||
{
|
||||
struct language_function *f;
|
||||
struct cp_language_function *f;
|
||||
|
||||
/* Save the language-specific per-function data so that we can
|
||||
get it back when we really expand this function. */
|
||||
@ -14045,15 +14041,15 @@ save_function_data (decl)
|
||||
19990908);
|
||||
|
||||
/* Make a copy. */
|
||||
f = ((struct language_function *)
|
||||
xmalloc (sizeof (struct language_function)));
|
||||
f = ((struct cp_language_function *)
|
||||
xmalloc (sizeof (struct cp_language_function)));
|
||||
bcopy ((char *) cp_function_chain, (char *) f,
|
||||
sizeof (struct language_function));
|
||||
sizeof (struct cp_language_function));
|
||||
DECL_SAVED_FUNCTION_DATA (decl) = f;
|
||||
|
||||
/* Clear out the bits we don't need. */
|
||||
f->x_stmt_tree.x_last_stmt = NULL_TREE;
|
||||
f->x_stmt_tree.x_last_expr_type = NULL_TREE;
|
||||
f->base.x_stmt_tree.x_last_stmt = NULL_TREE;
|
||||
f->base.x_stmt_tree.x_last_expr_type = NULL_TREE;
|
||||
f->x_result_rtx = NULL_RTX;
|
||||
f->x_named_label_uses = NULL;
|
||||
f->bindings = NULL;
|
||||
@ -14075,7 +14071,7 @@ finish_constructor_body ()
|
||||
{
|
||||
/* Any return from a constructor will end up here. */
|
||||
if (ctor_label)
|
||||
add_tree (build_stmt (LABEL_STMT, ctor_label));
|
||||
add_stmt (build_stmt (LABEL_STMT, ctor_label));
|
||||
|
||||
/* Clear CTOR_LABEL so that finish_return_stmt knows to really
|
||||
generate the return, rather than a goto to CTOR_LABEL. */
|
||||
@ -14084,7 +14080,7 @@ finish_constructor_body ()
|
||||
constructor to a return of `this'. */
|
||||
finish_return_stmt (NULL_TREE);
|
||||
/* Mark the end of the constructor. */
|
||||
add_tree (build_stmt (CTOR_STMT));
|
||||
add_stmt (build_stmt (CTOR_STMT));
|
||||
}
|
||||
|
||||
/* At the end of every destructor we generate code to restore virtual
|
||||
@ -14103,7 +14099,7 @@ finish_destructor_body ()
|
||||
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
|
||||
|
||||
/* Any return from a destructor will end up here. */
|
||||
add_tree (build_stmt (LABEL_STMT, dtor_label));
|
||||
add_stmt (build_stmt (LABEL_STMT, dtor_label));
|
||||
|
||||
/* Generate the code to call destructor on base class. If this
|
||||
destructor belongs to a class with virtual functions, then set
|
||||
@ -14896,10 +14892,10 @@ static void
|
||||
push_cp_function_context (f)
|
||||
struct function *f;
|
||||
{
|
||||
struct language_function *p
|
||||
= ((struct language_function *)
|
||||
xcalloc (1, sizeof (struct language_function)));
|
||||
f->language = p;
|
||||
struct cp_language_function *p
|
||||
= ((struct cp_language_function *)
|
||||
xcalloc (1, sizeof (struct cp_language_function)));
|
||||
f->language = (struct language_function *) p;
|
||||
|
||||
/* It takes an explicit call to expand_body to generate RTL for a
|
||||
function. */
|
||||
@ -14907,7 +14903,7 @@ push_cp_function_context (f)
|
||||
|
||||
/* Whenever we start a new function, we destroy temporaries in the
|
||||
usual way. */
|
||||
current_stmt_tree->stmts_are_full_exprs_p = 1;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
|
||||
}
|
||||
|
||||
/* Free the language-specific parts of F, now that we've finished
|
||||
@ -14926,7 +14922,7 @@ pop_cp_function_context (f)
|
||||
|
||||
static void
|
||||
mark_lang_function (p)
|
||||
struct language_function *p;
|
||||
struct cp_language_function *p;
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
@ -14941,7 +14937,7 @@ mark_lang_function (p)
|
||||
ggc_mark_rtx (p->x_result_rtx);
|
||||
|
||||
mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
|
||||
mark_stmt_tree (&p->x_stmt_tree);
|
||||
mark_stmt_tree (&p->base.x_stmt_tree);
|
||||
mark_binding_level (&p->bindings);
|
||||
}
|
||||
|
||||
@ -14951,7 +14947,7 @@ static void
|
||||
mark_cp_function_context (f)
|
||||
struct function *f;
|
||||
{
|
||||
mark_lang_function (f->language);
|
||||
mark_lang_function ((struct cp_language_function *) f->language);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1228,11 +1228,11 @@ build_aggr_init (exp, init, flags)
|
||||
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
|
||||
begin_init_stmts (&stmt_expr, &compound_stmt);
|
||||
destroy_temps = stmts_are_full_exprs_p ();
|
||||
current_stmt_tree->stmts_are_full_exprs_p = 0;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p = 0;
|
||||
expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
|
||||
init, LOOKUP_NORMAL|flags);
|
||||
stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
|
||||
current_stmt_tree->stmts_are_full_exprs_p = destroy_temps;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
|
||||
TREE_TYPE (exp) = type;
|
||||
TREE_READONLY (exp) = was_const;
|
||||
TREE_THIS_VOLATILE (exp) = was_volatile;
|
||||
@ -2873,7 +2873,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
|
||||
|
||||
begin_init_stmts (&stmt_expr, &compound_stmt);
|
||||
destroy_temps = stmts_are_full_exprs_p ();
|
||||
current_stmt_tree->stmts_are_full_exprs_p = 0;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p = 0;
|
||||
rval = get_temp_regvar (ptype,
|
||||
cp_convert (ptype, default_conversion (base)));
|
||||
base = get_temp_regvar (ptype, rval);
|
||||
@ -3035,9 +3035,9 @@ build_vec_init (decl, base, maxindex, init, from_array)
|
||||
}
|
||||
else
|
||||
{
|
||||
current_stmt_tree->stmts_are_full_exprs_p = 1;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
|
||||
finish_expr_stmt (elt_init);
|
||||
current_stmt_tree->stmts_are_full_exprs_p = 0;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p = 0;
|
||||
}
|
||||
|
||||
finish_expr_stmt (build_modify_expr
|
||||
@ -3087,7 +3087,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
|
||||
finish_expr_stmt (rval);
|
||||
|
||||
stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
|
||||
current_stmt_tree->stmts_are_full_exprs_p = destroy_temps;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
|
||||
return stmt_expr;
|
||||
}
|
||||
|
||||
|
@ -48,27 +48,20 @@
|
||||
|
||||
static tree maybe_convert_cond PARAMS ((tree));
|
||||
static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *));
|
||||
static tree prune_unused_decls PARAMS ((tree *, int *, void *));
|
||||
static void deferred_type_access_control PARAMS ((void));
|
||||
static void emit_associated_thunks PARAMS ((tree));
|
||||
|
||||
/* Record the fact that STMT was the last statement added to the
|
||||
statement tree. */
|
||||
|
||||
#define SET_LAST_STMT(stmt) \
|
||||
(current_stmt_tree->x_last_stmt = (stmt))
|
||||
|
||||
/* When parsing a template, LAST_TREE contains the last statement
|
||||
parsed. These are chained together through the TREE_CHAIN field,
|
||||
but often need to be re-organized since the parse is performed
|
||||
bottom-up. This macro makes LAST_TREE the indicated SUBSTMT of
|
||||
STMT. */
|
||||
|
||||
#define RECHAIN_STMTS(stmt, substmt) \
|
||||
do { \
|
||||
substmt = TREE_CHAIN (stmt); \
|
||||
TREE_CHAIN (stmt) = NULL_TREE; \
|
||||
SET_LAST_STMT (stmt); \
|
||||
#define RECHAIN_STMTS(stmt, substmt) \
|
||||
do { \
|
||||
substmt = TREE_CHAIN (stmt); \
|
||||
TREE_CHAIN (stmt) = NULL_TREE; \
|
||||
last_tree = stmt; \
|
||||
} while (0)
|
||||
|
||||
/* Finish processing the COND, the SUBSTMT condition for STMT. */
|
||||
@ -108,7 +101,19 @@ set_current_function_name_declared (i)
|
||||
int
|
||||
stmts_are_full_exprs_p ()
|
||||
{
|
||||
return current_stmt_tree->stmts_are_full_exprs_p;
|
||||
return current_stmt_tree ()->stmts_are_full_exprs_p;
|
||||
}
|
||||
|
||||
/* Returns the stmt_tree (if any) to which statements are currently
|
||||
being added. If there is no active statement-tree, NULL is
|
||||
returned. */
|
||||
|
||||
stmt_tree
|
||||
current_stmt_tree ()
|
||||
{
|
||||
return (cfun
|
||||
? &cfun->language->x_stmt_tree
|
||||
: &scope_chain->x_stmt_tree);
|
||||
}
|
||||
|
||||
/* One if we have already declared __FUNCTION__ (and related
|
||||
@ -170,20 +175,6 @@ do_pushlevel ()
|
||||
}
|
||||
}
|
||||
|
||||
/* T is a statement. Add it to the statement-tree. */
|
||||
|
||||
void
|
||||
add_tree (t)
|
||||
tree t;
|
||||
{
|
||||
/* Add T to the statement-tree. */
|
||||
TREE_CHAIN (last_tree) = t;
|
||||
SET_LAST_STMT (t);
|
||||
/* When we expand a statement-tree, we must know whether or not the
|
||||
statements are full-expresions. We record that fact here. */
|
||||
STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
|
||||
}
|
||||
|
||||
/* Finish a goto-statement. */
|
||||
|
||||
void
|
||||
@ -207,7 +198,7 @@ finish_goto_stmt (destination)
|
||||
|
||||
check_goto (destination);
|
||||
|
||||
add_tree (build_stmt (GOTO_STMT, destination));
|
||||
add_stmt (build_stmt (GOTO_STMT, destination));
|
||||
}
|
||||
|
||||
/* COND is the condition-expression for an if, while, etc.,
|
||||
@ -251,7 +242,7 @@ finish_expr_stmt (expr)
|
||||
if (!processing_template_decl)
|
||||
expr = break_out_cleanups (expr);
|
||||
|
||||
add_tree (build_stmt (EXPR_STMT, expr));
|
||||
add_stmt (build_stmt (EXPR_STMT, expr));
|
||||
}
|
||||
|
||||
finish_stmt ();
|
||||
@ -271,7 +262,7 @@ begin_if_stmt ()
|
||||
tree r;
|
||||
do_pushlevel ();
|
||||
r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -295,7 +286,7 @@ finish_then_clause (if_stmt)
|
||||
tree if_stmt;
|
||||
{
|
||||
RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
|
||||
SET_LAST_STMT (if_stmt);
|
||||
last_tree = if_stmt;
|
||||
return if_stmt;
|
||||
}
|
||||
|
||||
@ -346,7 +337,7 @@ begin_while_stmt ()
|
||||
{
|
||||
tree r;
|
||||
r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
do_pushlevel ();
|
||||
return r;
|
||||
}
|
||||
@ -382,7 +373,7 @@ tree
|
||||
begin_do_stmt ()
|
||||
{
|
||||
tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE);
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -440,7 +431,7 @@ finish_return_stmt (expr)
|
||||
return;
|
||||
}
|
||||
}
|
||||
add_tree (build_stmt (RETURN_STMT, expr));
|
||||
add_stmt (build_stmt (RETURN_STMT, expr));
|
||||
finish_stmt ();
|
||||
}
|
||||
|
||||
@ -454,7 +445,7 @@ begin_for_stmt ()
|
||||
r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
|
||||
NULL_TREE, NULL_TREE);
|
||||
NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
if (NEW_FOR_SCOPE_P (r))
|
||||
{
|
||||
do_pushlevel ();
|
||||
@ -521,7 +512,7 @@ finish_for_stmt (for_stmt)
|
||||
void
|
||||
finish_break_stmt ()
|
||||
{
|
||||
add_tree (build_stmt (BREAK_STMT));
|
||||
add_stmt (build_stmt (BREAK_STMT));
|
||||
}
|
||||
|
||||
/* Finish a continue-statement. */
|
||||
@ -529,7 +520,7 @@ finish_break_stmt ()
|
||||
void
|
||||
finish_continue_stmt ()
|
||||
{
|
||||
add_tree (build_stmt (CONTINUE_STMT));
|
||||
add_stmt (build_stmt (CONTINUE_STMT));
|
||||
}
|
||||
|
||||
/* Begin a switch-statement. Returns a new SWITCH_STMT if
|
||||
@ -540,7 +531,7 @@ begin_switch_stmt ()
|
||||
{
|
||||
tree r;
|
||||
r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE);
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
do_pushlevel ();
|
||||
return r;
|
||||
}
|
||||
@ -593,7 +584,7 @@ finish_case_label (low_value, high_value)
|
||||
{
|
||||
/* Add a representation for the case label to the statement
|
||||
tree. */
|
||||
add_tree (build_stmt (CASE_LABEL, low_value, high_value));
|
||||
add_stmt (build_stmt (CASE_LABEL, low_value, high_value));
|
||||
/* And warn about crossing initializations, etc. */
|
||||
if (!processing_template_decl)
|
||||
define_case_label ();
|
||||
@ -649,7 +640,7 @@ tree
|
||||
begin_try_block ()
|
||||
{
|
||||
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -660,7 +651,7 @@ begin_function_try_block ()
|
||||
{
|
||||
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
|
||||
FN_TRY_BLOCK_P (r) = 1;
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -761,7 +752,7 @@ begin_handler ()
|
||||
{
|
||||
tree r;
|
||||
r = build_stmt (HANDLER, NULL_TREE, NULL_TREE);
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
do_pushlevel ();
|
||||
return r;
|
||||
}
|
||||
@ -813,7 +804,7 @@ void
|
||||
begin_catch_block (type)
|
||||
tree type;
|
||||
{
|
||||
add_tree (build (START_CATCH_STMT, type));
|
||||
add_stmt (build (START_CATCH_STMT, type));
|
||||
}
|
||||
|
||||
/* Finish a handler, which may be given by HANDLER. The BLOCKs are
|
||||
@ -861,7 +852,7 @@ begin_compound_stmt (has_no_scope)
|
||||
if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK)
|
||||
is_try = 1;
|
||||
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
if (has_no_scope)
|
||||
COMPOUND_STMT_NO_SCOPE (r) = 1;
|
||||
|
||||
@ -957,7 +948,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
|
||||
r = build_stmt (ASM_STMT, cv_qualifier, string,
|
||||
output_operands, input_operands,
|
||||
clobbers);
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
}
|
||||
|
||||
/* Finish a label with the indicated NAME. */
|
||||
@ -967,7 +958,7 @@ finish_label_stmt (name)
|
||||
tree name;
|
||||
{
|
||||
tree decl = define_label (input_filename, lineno, name);
|
||||
add_tree (build_stmt (LABEL_STMT, decl));
|
||||
add_stmt (build_stmt (LABEL_STMT, decl));
|
||||
}
|
||||
|
||||
/* Finish a series of declarations for local labels. G++ allows users
|
||||
@ -993,7 +984,7 @@ add_decl_stmt (decl)
|
||||
|
||||
/* We need the type to last until instantiation time. */
|
||||
decl_stmt = build_stmt (DECL_STMT, decl);
|
||||
add_tree (decl_stmt);
|
||||
add_stmt (decl_stmt);
|
||||
}
|
||||
|
||||
/* Generate the RTL for a SUBOBJECT. */
|
||||
@ -1014,7 +1005,7 @@ finish_subobject (cleanup)
|
||||
tree cleanup;
|
||||
{
|
||||
tree r = build_stmt (SUBOBJECT, cleanup);
|
||||
add_tree (r);
|
||||
add_stmt (r);
|
||||
}
|
||||
|
||||
/* When DECL goes out of scope, make sure that CLEANUP is executed. */
|
||||
@ -1024,7 +1015,7 @@ finish_decl_cleanup (decl, cleanup)
|
||||
tree decl;
|
||||
tree cleanup;
|
||||
{
|
||||
add_tree (build_stmt (CLEANUP_STMT, decl, cleanup));
|
||||
add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
|
||||
}
|
||||
|
||||
/* Generate the RTL for a RETURN_INIT. */
|
||||
@ -1103,10 +1094,10 @@ finish_named_return_value (return_id, init)
|
||||
if (!processing_template_decl)
|
||||
{
|
||||
cp_finish_decl (decl, init, NULL_TREE, 0);
|
||||
add_tree (build_stmt (RETURN_INIT, NULL_TREE, NULL_TREE));
|
||||
add_stmt (build_stmt (RETURN_INIT, NULL_TREE, NULL_TREE));
|
||||
}
|
||||
else
|
||||
add_tree (build_stmt (RETURN_INIT, return_id, init));
|
||||
add_stmt (build_stmt (RETURN_INIT, return_id, init));
|
||||
}
|
||||
|
||||
/* Don't use tree-inlining for functions with named return values.
|
||||
@ -1192,7 +1183,7 @@ setup_vtbl_ptr (member_init_list, base_init_list)
|
||||
if (DECL_CONSTRUCTOR_P (current_function_decl))
|
||||
{
|
||||
if (processing_template_decl)
|
||||
add_tree (build_min_nt
|
||||
add_stmt (build_min_nt
|
||||
(CTOR_INITIALIZER,
|
||||
member_init_list, base_init_list));
|
||||
else
|
||||
@ -1202,7 +1193,7 @@ setup_vtbl_ptr (member_init_list, base_init_list)
|
||||
/* Mark the beginning of the constructor. */
|
||||
ctor_stmt = build_stmt (CTOR_STMT);
|
||||
CTOR_BEGIN_P (ctor_stmt) = 1;
|
||||
add_tree (ctor_stmt);
|
||||
add_stmt (ctor_stmt);
|
||||
|
||||
/* And actually initialize the base-classes and members. */
|
||||
emit_base_init (member_init_list, base_init_list);
|
||||
@ -1299,7 +1290,7 @@ add_scope_stmt (begin_p, partial_p)
|
||||
}
|
||||
|
||||
/* Add the new statement to the statement-tree. */
|
||||
add_tree (ss);
|
||||
add_stmt (ss);
|
||||
|
||||
return top;
|
||||
}
|
||||
@ -1391,7 +1382,7 @@ finish_stmt_expr (rtl_expr)
|
||||
|
||||
/* Remove the compound statement from the tree structure; it is
|
||||
now saved in the STMT_EXPR. */
|
||||
SET_LAST_STMT (rtl_expr);
|
||||
last_tree = rtl_expr;
|
||||
TREE_CHAIN (last_tree) = NULL_TREE;
|
||||
|
||||
/* If we created a statement-tree for this statement-expression,
|
||||
@ -2223,103 +2214,6 @@ finish_typeof (expr)
|
||||
return TREE_TYPE (expr);
|
||||
}
|
||||
|
||||
/* Remove declarations of internal variables that are not used from a
|
||||
stmt tree. To qualify, the variable must have a name and must have
|
||||
a zero DECL_SOURCE_LINE. We tried to remove all variables for
|
||||
which TREE_USED was false, but it turns out that there's tons of
|
||||
variables for which TREE_USED is false but that are still in fact
|
||||
used. */
|
||||
|
||||
static tree
|
||||
prune_unused_decls (tp, walk_subtrees, data)
|
||||
tree *tp;
|
||||
int *walk_subtrees ATTRIBUTE_UNUSED;
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
tree t = *tp;
|
||||
|
||||
if (t == NULL_TREE)
|
||||
{
|
||||
*walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (TREE_CODE (t) == DECL_STMT)
|
||||
{
|
||||
tree d = DECL_STMT_DECL (t);
|
||||
if (!TREE_USED (d) && DECL_NAME (d) && DECL_SOURCE_LINE (d) == 0)
|
||||
{
|
||||
*tp = TREE_CHAIN (t);
|
||||
/* Recurse on the new value of tp, otherwise we will skip
|
||||
the next statement. */
|
||||
return prune_unused_decls (tp, walk_subtrees, data);
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (t) == SCOPE_STMT)
|
||||
{
|
||||
/* Remove all unused decls from the BLOCK of this SCOPE_STMT. */
|
||||
tree block = SCOPE_STMT_BLOCK (t);
|
||||
|
||||
if (block)
|
||||
{
|
||||
tree *vp;
|
||||
|
||||
for (vp = &BLOCK_VARS (block); *vp; )
|
||||
{
|
||||
tree v = *vp;
|
||||
if (! TREE_USED (v) && DECL_NAME (v) && DECL_SOURCE_LINE (v) == 0)
|
||||
*vp = TREE_CHAIN (v); /* drop */
|
||||
else
|
||||
vp = &TREE_CHAIN (v); /* advance */
|
||||
}
|
||||
/* If there are now no variables, the entire BLOCK can be dropped.
|
||||
(This causes SCOPE_NULLIFIED_P (t) to be true.) */
|
||||
if (BLOCK_VARS (block) == NULL_TREE)
|
||||
SCOPE_STMT_BLOCK (t) = NULL_TREE;
|
||||
}
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Create an empty statement tree rooted at T. */
|
||||
|
||||
void
|
||||
begin_stmt_tree (t)
|
||||
tree *t;
|
||||
{
|
||||
/* We create a trivial EXPR_STMT so that last_tree is never NULL in
|
||||
what follows. We remove the extraneous statement in
|
||||
finish_stmt_tree. */
|
||||
*t = build_nt (EXPR_STMT, void_zero_node);
|
||||
SET_LAST_STMT (*t);
|
||||
last_expr_type = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Finish the statement tree rooted at T. */
|
||||
|
||||
void
|
||||
finish_stmt_tree (t)
|
||||
tree *t;
|
||||
{
|
||||
tree stmt;
|
||||
|
||||
/* Remove the fake extra statement added in begin_stmt_tree. */
|
||||
stmt = TREE_CHAIN (*t);
|
||||
*t = stmt;
|
||||
SET_LAST_STMT (NULL_TREE);
|
||||
|
||||
/* Remove unused decls from the stmt tree. */
|
||||
walk_stmt_tree (t, prune_unused_decls, NULL);
|
||||
|
||||
if (cfun)
|
||||
{
|
||||
/* The line-number recorded in the outermost statement in a function
|
||||
is the line number of the end of the function. */
|
||||
STMT_LINENO (stmt) = lineno;
|
||||
STMT_LINENO_FOR_FN_P (stmt) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We're about to expand T, a statement. Set up appropriate context
|
||||
for the substitution. */
|
||||
|
||||
@ -2329,7 +2223,7 @@ prep_stmt (t)
|
||||
{
|
||||
if (!STMT_LINENO_FOR_FN_P (t))
|
||||
lineno = STMT_LINENO (t);
|
||||
current_stmt_tree->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
|
||||
}
|
||||
|
||||
/* Generate RTL for the statement T, and its substatements, and any
|
||||
@ -2453,7 +2347,8 @@ lang_expand_stmt (t)
|
||||
}
|
||||
|
||||
/* Restore saved state. */
|
||||
current_stmt_tree->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
|
||||
current_stmt_tree ()->stmts_are_full_exprs_p =
|
||||
saved_stmts_are_full_exprs_p;
|
||||
|
||||
/* Go on to the next statement in this scope. */
|
||||
t = TREE_CHAIN (t);
|
||||
|
@ -42,7 +42,6 @@ static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int));
|
||||
static tree no_linkage_helper PARAMS ((tree *, int *, void *));
|
||||
static tree build_srcloc PARAMS ((const char *, int));
|
||||
static void mark_list_hash PARAMS ((void *));
|
||||
static int statement_code_p PARAMS ((enum tree_code));
|
||||
static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *));
|
||||
static tree cp_unsave_r PARAMS ((tree *, int *, void *));
|
||||
static void cp_unsave PARAMS ((tree *));
|
||||
@ -50,6 +49,7 @@ static tree build_target_expr PARAMS ((tree, tree));
|
||||
static tree count_trees_r PARAMS ((tree *, int *, void *));
|
||||
static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
|
||||
static tree find_tree_r PARAMS ((tree *, int *, void *));
|
||||
extern int cp_statement_code_p PARAMS ((enum tree_code));
|
||||
|
||||
/* If REF is an lvalue, returns the kind of lvalue that REF is.
|
||||
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
|
||||
@ -1071,33 +1071,18 @@ is_aggr_type_2 (t1, t2)
|
||||
|
||||
/* Returns non-zero if CODE is the code for a statement. */
|
||||
|
||||
static int
|
||||
statement_code_p (code)
|
||||
int
|
||||
cp_statement_code_p (code)
|
||||
enum tree_code code;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case EXPR_STMT:
|
||||
case COMPOUND_STMT:
|
||||
case DECL_STMT:
|
||||
case IF_STMT:
|
||||
case FOR_STMT:
|
||||
case WHILE_STMT:
|
||||
case DO_STMT:
|
||||
case RETURN_STMT:
|
||||
case BREAK_STMT:
|
||||
case CONTINUE_STMT:
|
||||
case SWITCH_STMT:
|
||||
case GOTO_STMT:
|
||||
case LABEL_STMT:
|
||||
case ASM_STMT:
|
||||
case SUBOBJECT:
|
||||
case CLEANUP_STMT:
|
||||
case START_CATCH_STMT:
|
||||
case CTOR_STMT:
|
||||
case SCOPE_STMT:
|
||||
case CTOR_INITIALIZER:
|
||||
case CASE_LABEL:
|
||||
case RETURN_INIT:
|
||||
case TRY_BLOCK:
|
||||
case HANDLER:
|
||||
@ -1223,9 +1208,9 @@ copy_template_template_parm (t, newargs)
|
||||
/* Apply FUNC to all the sub-trees of TP in a pre-order traversal.
|
||||
FUNC is called with the DATA and the address of each sub-tree. If
|
||||
FUNC returns a non-NULL value, the traversal is aborted, and the
|
||||
value returned by FUNC is returned. The FLAGS govern the way in
|
||||
which nodes are walked. If HTAB is non-NULL it is used to record
|
||||
the nodes visited, and to avoid visiting a node more than once. */
|
||||
value returned by FUNC is returned. If HTAB is non-NULL it is used
|
||||
to record the nodes visited, and to avoid visiting a node more than
|
||||
once. */
|
||||
|
||||
tree
|
||||
walk_tree (tp, func, data, htab)
|
||||
@ -1455,73 +1440,6 @@ walk_tree_without_duplicates (tp, func, data)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Like walk_tree, but only examines statement nodes. We don't need a
|
||||
without_duplicates variant of this one because the statement tree is
|
||||
a tree, not a graph. */
|
||||
|
||||
tree
|
||||
walk_stmt_tree (tp, func, data)
|
||||
tree *tp;
|
||||
walk_tree_fn func;
|
||||
void *data;
|
||||
{
|
||||
enum tree_code code;
|
||||
int walk_subtrees;
|
||||
tree result;
|
||||
int i, len;
|
||||
|
||||
#define WALK_SUBTREE(NODE) \
|
||||
do \
|
||||
{ \
|
||||
result = walk_stmt_tree (&(NODE), func, data); \
|
||||
if (result) \
|
||||
return result; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Skip empty subtrees. */
|
||||
if (!*tp)
|
||||
return NULL_TREE;
|
||||
|
||||
/* Skip subtrees below non-statement nodes. */
|
||||
if (!statement_code_p (TREE_CODE (*tp)))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Call the function. */
|
||||
walk_subtrees = 1;
|
||||
result = (*func) (tp, &walk_subtrees, data);
|
||||
|
||||
/* If we found something, return it. */
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
/* Even if we didn't, FUNC may have decided that there was nothing
|
||||
interesting below this point in the tree. */
|
||||
if (!walk_subtrees)
|
||||
return NULL_TREE;
|
||||
|
||||
/* FUNC may have modified the tree, recheck that we're looking at a
|
||||
statement node. */
|
||||
code = TREE_CODE (*tp);
|
||||
if (!statement_code_p (code))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Walk over all the sub-trees of this operand. Statement nodes never
|
||||
contain RTL, and we needn't worry about TARGET_EXPRs. */
|
||||
len = TREE_CODE_LENGTH (code);
|
||||
|
||||
/* Go through the subtrees. We need to do this in forward order so
|
||||
that the scope of a FOR_EXPR is handled properly. */
|
||||
for (i = 0; i < len; ++i)
|
||||
WALK_SUBTREE (TREE_OPERAND (*tp, i));
|
||||
|
||||
/* Finally visit the chain. This can be tail-recursion optimized if
|
||||
we write it this way. */
|
||||
return walk_stmt_tree (&TREE_CHAIN (*tp), func, data);
|
||||
|
||||
#undef WALK_SUBTREE
|
||||
}
|
||||
|
||||
/* Called from count_trees via walk_tree. */
|
||||
|
||||
static tree
|
||||
@ -2477,6 +2395,7 @@ init_tree ()
|
||||
{
|
||||
make_lang_type_fn = cp_make_lang_type;
|
||||
lang_unsave = cp_unsave;
|
||||
lang_statement_code_p = cp_statement_code_p;
|
||||
ggc_add_root (list_hash_table,
|
||||
ARRAY_SIZE (list_hash_table),
|
||||
sizeof (struct list_hash *),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* This is part of libio/iostream, providing -*- C++ -*- input/output.
|
||||
Copyright (C) 1993 Free Software Foundation
|
||||
Copyright (C) 1993, 2000 Free Software Foundation
|
||||
|
||||
This file is part of the GNU IO Library. This library is free
|
||||
software; you can redistribute it and/or modify it under the
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Encoding of types for Objective C.
|
||||
Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup
|
||||
Bitfield support by Ovidiu Predescu
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user