06ceef4e7b
* c-common.c (decl_attributes): Set DECL_SIZE_UNIT. * c-decl.c (duplicate_decls, finish_enum): Likewise. (finish_decl): Remove -Wlarger-than code from here. * flags.h (id_clash_len): Now int. (larger_than_size): Now HOST_WIDE_INT. * fold-const.c (size_int_wide): No more HIGH parm; NUMBER is signed. Clean up checking to see if in table. (make_bit_field_ref): Remove extra parm to bitsize_int. * ggc-common.c (ggc_mark_tree_children): Mark DECL_SIZE_UNIT. * print-tree.c (print_node): Print DECL_SIZE_UNIT and TYPE_SIZE_UNIT. * stmt.c (expand_decl): Use DECL_SIZE_UNIT for stack checking size and for computing size of decl. * stor-layout.c (layout_decl): Set DECL_SIZE_UNIT. Move -Wlarger-than code to here. (layout_record): Remove extra arg to bitsize_int. Set TYPE_BINFO_SIZE_UNIT. (layout_union): Remove extra arg to bitsize_int. Use proper type for size of QUAL_UNION. (layout_type): Remove extra arg to bitsize_int. * toplev.c (id_clash_len): Now int. (larger_than_size): Now HOST_WIDE_INT. (decode_W_option): Clean up id-clash and larger-than- cases. * tree.c (get_identifier, maybe_get_identifier): Remove unneeded casts. (expr_align, case FUNCTION_DECL): DECL_ALIGN is not defined. * tree.h (BINFO_SIZE_UNIT, TYPE_BINFO_SIZE_UNIT, DECL_SIZE_UNIT): New. (struct tree_decl): New field size_unit. (size_int_wide): No HIGH operand; NUMBER is now signed. (size_int_2): Deleted. (size_int, bitsize_int): Don't use it and rework args. * varasm.c (assemble_variable, output_constructor): Use DECL_SIZE_UNIT. * ch/decl.c (layout_enum): Set DECL_SIZE_UNIT. * ch/satisfy.c (safe_satisfy_decl): Likewise. * cp/class.c (build_primary_vtable, layout_vtable_decl): Likewise. (avoid_overlap, build_base_field): Likewise. (build_base_field, build_base_fields, is_empty_class): Test DECL_SIZE with integer_zero. (layout_class_type): Set CLASSTYPE_SIZE_UNIT. * cp/cp-tree.h (struct lang_type): New field size_unit. (CLASSTYPE_SIZE_UNIT): New macro. * cp/decl.c (init_decl_processing): Set DECL_SIZE_UNIT. (cp_finish_decl): Delete -Wlarger-than processing. * cp/optimize.c (remap_decl): Walk DECL_SIZE_UNIT. * cp/pt.c (tsubst_decl): Set DECL_SIZE_UNIT. * cp/tree.c (make_binfo): binfo vector is one entry longer. (walk_tree): Walk DECL_SIZE_UNIT. * f/com.c (ffecom_sym_transform): Use DECL_SIZE_UNIT. (ffecom_transform_common_, ffecom_transform_equiv_): Likewise. (duplicate_decls): Likewise. (ffecom_tree_canonize_ptr_): Delete extra arg to bitsize_int. (finish_decl): Delete -Wlarger-than processing. * java/class.c (build_class_ref, push_super_field): Set DECL_SIZE_UNIT. * java/constants.c (build_constants_constructor): Likewise. From-SVN: r32068
629 lines
18 KiB
C
629 lines
18 KiB
C
/* Name-satisfaction for GNU Chill compiler.
|
|
Copyright (C) 1993, 1998, 1999, 2000 Free Software Foundation, Inc.
|
|
|
|
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, 59 Temple Place - Suite 330,
|
|
Boston, MA 02111-1307, USA. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "tree.h"
|
|
#include "flags.h"
|
|
#include "ch-tree.h"
|
|
#include "lex.h"
|
|
#include "toplev.h"
|
|
|
|
#define SATISFY(ARG) ((ARG) = satisfy(ARG, chain))
|
|
|
|
struct decl_chain
|
|
{
|
|
struct decl_chain *prev;
|
|
/* DECL can be a decl, or a POINTER_TYPE or a REFERENCE_TYPE. */
|
|
tree decl;
|
|
};
|
|
|
|
/* forward declarations */
|
|
static tree satisfy PARAMS ((tree, struct decl_chain *));
|
|
static void cycle_error_print PARAMS ((struct decl_chain *, tree));
|
|
static tree safe_satisfy_decl PARAMS ((tree, struct decl_chain *));
|
|
static void satisfy_list PARAMS ((tree, struct decl_chain *));
|
|
static void satisfy_list_values PARAMS ((tree, struct decl_chain *));
|
|
|
|
static struct decl_chain dummy_chain;
|
|
#define LOOKUP_ONLY (chain==&dummy_chain)
|
|
|
|
/* Recursive helper routine to logically reverse the chain. */
|
|
static void
|
|
cycle_error_print (chain, decl)
|
|
struct decl_chain *chain;
|
|
tree decl;
|
|
{
|
|
if (chain->decl != decl)
|
|
{
|
|
cycle_error_print (chain->prev, decl);
|
|
if (TREE_CODE_CLASS (TREE_CODE (chain->decl)) == 'd')
|
|
error_with_decl (chain->decl, " `%s', which depends on ...");
|
|
}
|
|
}
|
|
|
|
static tree
|
|
safe_satisfy_decl (decl, prev_chain)
|
|
tree decl;
|
|
struct decl_chain *prev_chain;
|
|
{
|
|
struct decl_chain new_link;
|
|
struct decl_chain *link;
|
|
struct decl_chain *chain = prev_chain;
|
|
char *save_filename = input_filename;
|
|
int save_lineno = lineno;
|
|
tree result = decl;
|
|
|
|
if (decl == NULL_TREE)
|
|
return decl;
|
|
|
|
if (!LOOKUP_ONLY)
|
|
{
|
|
int pointer_type_breaks_cycle = 0;
|
|
/* Look for a cycle.
|
|
We could do this test more efficiently by setting a flag. FIXME */
|
|
for (link = prev_chain; link != NULL; link = link->prev)
|
|
{
|
|
if (TREE_CODE_CLASS (TREE_CODE (link->decl)) != 'd')
|
|
pointer_type_breaks_cycle = 1;
|
|
if (link->decl == decl)
|
|
{
|
|
if (!pointer_type_breaks_cycle)
|
|
{
|
|
error_with_decl (decl, "Cycle: `%s' depends on ...");
|
|
cycle_error_print (prev_chain, decl);
|
|
error_with_decl (decl, " `%s'");
|
|
return error_mark_node;
|
|
}
|
|
/* There is a cycle, but it includes a pointer type,
|
|
so we're OK. However, we still have to continue
|
|
the satisfy (for example in case this is a TYPE_DECL
|
|
that points to a LANG_DECL). The cycle-check for
|
|
POINTER_TYPE/REFERENCE_TYPE should stop the recursion. */
|
|
break;
|
|
}
|
|
}
|
|
|
|
new_link.decl = decl;
|
|
new_link.prev = prev_chain;
|
|
chain = &new_link;
|
|
}
|
|
|
|
input_filename = DECL_SOURCE_FILE (decl);
|
|
lineno = DECL_SOURCE_LINE (decl);
|
|
|
|
switch ((enum chill_tree_code)TREE_CODE (decl))
|
|
{
|
|
case ALIAS_DECL:
|
|
if (!LOOKUP_ONLY && !DECL_POSTFIX_ALL(decl))
|
|
result = safe_satisfy_decl (DECL_ABSTRACT_ORIGIN (decl), chain);
|
|
break;
|
|
case BASED_DECL:
|
|
SATISFY (TREE_TYPE (decl));
|
|
SATISFY (DECL_ABSTRACT_ORIGIN (decl));
|
|
break;
|
|
case CONST_DECL:
|
|
SATISFY (TREE_TYPE (decl));
|
|
SATISFY (DECL_INITIAL (decl));
|
|
if (!LOOKUP_ONLY)
|
|
{
|
|
if (DECL_SIZE (decl) == 0)
|
|
{
|
|
tree init_expr = DECL_INITIAL (decl);
|
|
tree init_type;
|
|
tree specified_mode = TREE_TYPE (decl);
|
|
|
|
if (init_expr == NULL_TREE
|
|
|| TREE_CODE (init_expr) == ERROR_MARK)
|
|
goto bad_const;
|
|
init_type = TREE_TYPE (init_expr);
|
|
if (specified_mode == NULL_TREE)
|
|
{
|
|
if (init_type == NULL_TREE)
|
|
{
|
|
check_have_mode (init_expr, "SYN without mode");
|
|
goto bad_const;
|
|
}
|
|
TREE_TYPE (decl) = init_type;
|
|
CH_DERIVED_FLAG (decl) = CH_DERIVED_FLAG (init_expr);
|
|
}
|
|
else if (CH_IS_ASSOCIATION_MODE (specified_mode) ||
|
|
CH_IS_ACCESS_MODE (specified_mode) || CH_IS_TEXT_MODE (specified_mode) ||
|
|
CH_IS_BUFFER_MODE (specified_mode) || CH_IS_EVENT_MODE (specified_mode))
|
|
{
|
|
error ("SYN of this mode not allowed");
|
|
goto bad_const;
|
|
}
|
|
else if (!CH_COMPATIBLE (init_expr, specified_mode))
|
|
{
|
|
error ("mode of SYN incompatible with value");
|
|
goto bad_const;
|
|
}
|
|
else if (discrete_type_p (specified_mode)
|
|
&& TREE_CODE (init_expr) == INTEGER_CST
|
|
&& (compare_int_csts (LT_EXPR, init_expr,
|
|
TYPE_MIN_VALUE (specified_mode))
|
|
|| compare_int_csts (GT_EXPR, init_expr,
|
|
TYPE_MAX_VALUE(specified_mode))
|
|
))
|
|
{
|
|
error ("SYN value outside range of its mode");
|
|
/* set an always-valid initial value to prevent
|
|
other errors. */
|
|
DECL_INITIAL (decl) = TYPE_MIN_VALUE (specified_mode);
|
|
}
|
|
else if (CH_STRING_TYPE_P (specified_mode)
|
|
&& (init_type && CH_STRING_TYPE_P (init_type))
|
|
&& integer_zerop (string_assignment_condition (specified_mode, init_expr)))
|
|
{
|
|
error ("INIT string too large for mode");
|
|
DECL_INITIAL (decl) = error_mark_node;
|
|
}
|
|
else
|
|
{
|
|
struct ch_class class;
|
|
class.mode = TREE_TYPE (decl);
|
|
class.kind = CH_VALUE_CLASS;
|
|
DECL_INITIAL (decl)
|
|
= convert_to_class (class, DECL_INITIAL (decl));
|
|
}
|
|
/* DECL_SIZE is set to prevent re-doing this stuff. */
|
|
DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (decl));
|
|
DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
|
|
|
|
if (! TREE_CONSTANT (DECL_INITIAL (decl))
|
|
&& TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK)
|
|
{
|
|
error_with_decl (decl,
|
|
"value of %s is not a valid constant");
|
|
DECL_INITIAL (decl) = error_mark_node;
|
|
}
|
|
}
|
|
result = DECL_INITIAL (decl);
|
|
}
|
|
break;
|
|
bad_const:
|
|
DECL_INITIAL (decl) = error_mark_node;
|
|
TREE_TYPE (decl) = error_mark_node;
|
|
return error_mark_node;
|
|
case FUNCTION_DECL:
|
|
SATISFY (TREE_TYPE (decl));
|
|
if (CH_DECL_PROCESS (decl))
|
|
safe_satisfy_decl ((tree) DECL_TASKING_CODE_DECL (decl), prev_chain);
|
|
break;
|
|
case PARM_DECL:
|
|
SATISFY (TREE_TYPE (decl));
|
|
break;
|
|
/* RESULT_DECL doesn't need to be satisfied;
|
|
it's only built internally in pass 2 */
|
|
case TYPE_DECL:
|
|
SATISFY (TREE_TYPE (decl));
|
|
if (CH_DECL_SIGNAL (decl))
|
|
safe_satisfy_decl ((tree) DECL_TASKING_CODE_DECL (decl), prev_chain);
|
|
if (!LOOKUP_ONLY)
|
|
{
|
|
if (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE)
|
|
TYPE_NAME (TREE_TYPE (decl)) = decl;
|
|
layout_decl (decl, 0);
|
|
if (CH_DECL_SIGNAL (decl) && CH_TYPE_NONVALUE_P (TREE_TYPE (decl)))
|
|
error ("mode with non-value property in signal definition");
|
|
result = TREE_TYPE (decl);
|
|
}
|
|
break;
|
|
case VAR_DECL:
|
|
SATISFY (TREE_TYPE (decl));
|
|
if (!LOOKUP_ONLY)
|
|
{
|
|
layout_decl (decl, 0);
|
|
if (TREE_READONLY (TREE_TYPE (decl)))
|
|
TREE_READONLY (decl) = 1;
|
|
}
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
|
|
/* Now set the DECL_RTL, if needed. */
|
|
if (!LOOKUP_ONLY && DECL_RTL (decl) == 0
|
|
&& (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
|
|
|| TREE_CODE (decl) == CONST_DECL))
|
|
{
|
|
if (TREE_CODE (decl) == FUNCTION_DECL && decl_function_context (decl))
|
|
make_function_rtl (decl);
|
|
else if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
|
|
expand_decl (decl);
|
|
else
|
|
{ char * asm_name;
|
|
if (current_module == 0 || TREE_PUBLIC (decl)
|
|
|| current_function_decl)
|
|
asm_name = NULL;
|
|
else
|
|
{
|
|
asm_name = (char*)
|
|
alloca (IDENTIFIER_LENGTH (current_module->prefix_name)
|
|
+ IDENTIFIER_LENGTH (DECL_NAME (decl)) + 3);
|
|
sprintf (asm_name, "%s__%s",
|
|
IDENTIFIER_POINTER (current_module->prefix_name),
|
|
IDENTIFIER_POINTER (DECL_NAME (decl)));
|
|
}
|
|
make_decl_rtl (decl, asm_name, TREE_PUBLIC (decl));
|
|
}
|
|
}
|
|
|
|
input_filename = save_filename;
|
|
lineno = save_lineno;
|
|
|
|
return result;
|
|
}
|
|
|
|
tree
|
|
satisfy_decl (decl, lookup_only)
|
|
tree decl;
|
|
int lookup_only;
|
|
{
|
|
return safe_satisfy_decl (decl, lookup_only ? &dummy_chain : NULL);
|
|
}
|
|
|
|
static void
|
|
satisfy_list (exp, chain)
|
|
register tree exp;
|
|
struct decl_chain *chain;
|
|
{
|
|
for (; exp != NULL_TREE; exp = TREE_CHAIN (exp))
|
|
{
|
|
SATISFY (TREE_VALUE (exp));
|
|
SATISFY (TREE_PURPOSE (exp));
|
|
}
|
|
}
|
|
|
|
static void
|
|
satisfy_list_values (exp, chain)
|
|
register tree exp;
|
|
struct decl_chain *chain;
|
|
{
|
|
for (; exp != NULL_TREE; exp = TREE_CHAIN (exp))
|
|
{
|
|
SATISFY (TREE_VALUE (exp));
|
|
}
|
|
}
|
|
|
|
static tree
|
|
satisfy (exp, chain)
|
|
tree exp;
|
|
struct decl_chain *chain;
|
|
{
|
|
int arg_length;
|
|
int i;
|
|
tree decl;
|
|
|
|
if (exp == NULL_TREE)
|
|
return NULL_TREE;
|
|
|
|
#if 0
|
|
if (!UNSATISFIED (exp))
|
|
return exp;
|
|
#endif
|
|
|
|
switch (TREE_CODE_CLASS (TREE_CODE (exp)))
|
|
{
|
|
case 'd':
|
|
if (!LOOKUP_ONLY)
|
|
return safe_satisfy_decl (exp, chain);
|
|
break;
|
|
case 'r':
|
|
case 's':
|
|
case '<':
|
|
case 'e':
|
|
switch ((enum chill_tree_code)TREE_CODE (exp))
|
|
{
|
|
case REPLICATE_EXPR:
|
|
goto binary_op;
|
|
case TRUTH_NOT_EXPR:
|
|
goto unary_op;
|
|
case COMPONENT_REF:
|
|
SATISFY (TREE_OPERAND (exp, 0));
|
|
if (!LOOKUP_ONLY && TREE_TYPE (exp) == NULL_TREE)
|
|
return resolve_component_ref (exp);
|
|
return exp;
|
|
case CALL_EXPR:
|
|
SATISFY (TREE_OPERAND (exp, 0));
|
|
SATISFY (TREE_OPERAND (exp, 1));
|
|
if (!LOOKUP_ONLY && TREE_TYPE (exp) == NULL_TREE)
|
|
return build_generalized_call (TREE_OPERAND (exp, 0),
|
|
TREE_OPERAND (exp, 1));
|
|
return exp;
|
|
case CONSTRUCTOR:
|
|
{ tree link = TREE_OPERAND (exp, 1);
|
|
int expand_needed = TREE_TYPE (exp)
|
|
&& TREE_CODE_CLASS (TREE_CODE (TREE_TYPE (exp))) != 't';
|
|
for (; link != NULL_TREE; link = TREE_CHAIN (link))
|
|
{
|
|
SATISFY (TREE_VALUE (link));
|
|
if (!TUPLE_NAMED_FIELD (link))
|
|
SATISFY (TREE_PURPOSE (link));
|
|
}
|
|
SATISFY (TREE_TYPE (exp));
|
|
if (expand_needed && !LOOKUP_ONLY)
|
|
{
|
|
tree type = TREE_TYPE (exp);
|
|
TREE_TYPE (exp) = NULL_TREE; /* To force expansion. */
|
|
return chill_expand_tuple (type, exp);
|
|
}
|
|
return exp;
|
|
}
|
|
default:
|
|
;
|
|
}
|
|
arg_length = tree_code_length[TREE_CODE (exp)];
|
|
for (i = 0; i < arg_length; i++)
|
|
SATISFY (TREE_OPERAND (exp, i));
|
|
return exp;
|
|
case '1':
|
|
unary_op:
|
|
SATISFY (TREE_OPERAND (exp, 0));
|
|
if ((enum chill_tree_code)TREE_CODE (exp) == PAREN_EXPR)
|
|
return TREE_OPERAND (exp, 0);
|
|
if (!LOOKUP_ONLY)
|
|
return finish_chill_unary_op (exp);
|
|
break;
|
|
case '2':
|
|
binary_op:
|
|
SATISFY (TREE_OPERAND (exp, 0));
|
|
SATISFY (TREE_OPERAND (exp, 1));
|
|
if (!LOOKUP_ONLY && TREE_CODE (exp) != RANGE_EXPR)
|
|
return finish_chill_binary_op (exp);
|
|
break;
|
|
case 'x':
|
|
switch ((enum chill_tree_code)TREE_CODE (exp))
|
|
{
|
|
case IDENTIFIER_NODE:
|
|
decl = lookup_name (exp);
|
|
if (decl == NULL)
|
|
{
|
|
if (LOOKUP_ONLY)
|
|
return exp;
|
|
error ("undeclared identifier `%s'", IDENTIFIER_POINTER (exp));
|
|
return error_mark_node;
|
|
}
|
|
if (LOOKUP_ONLY)
|
|
return decl;
|
|
return safe_satisfy_decl (decl, chain);
|
|
case TREE_LIST:
|
|
satisfy_list (exp, chain);
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
break;
|
|
case 't':
|
|
/* If TYPE_SIZE is non-NULL, exp and its subfields has already been
|
|
satified and laid out. The exception is pointer and reference types,
|
|
which we layout before we lay out their TREE_TYPE. */
|
|
if (TYPE_SIZE (exp) && TREE_CODE (exp) != POINTER_TYPE
|
|
&& TREE_CODE (exp) != REFERENCE_TYPE)
|
|
return exp;
|
|
if (TYPE_MAIN_VARIANT (exp) != exp)
|
|
SATISFY (TYPE_MAIN_VARIANT (exp));
|
|
switch ((enum chill_tree_code)TREE_CODE (exp))
|
|
{
|
|
case LANG_TYPE:
|
|
{
|
|
tree d = TYPE_DOMAIN (exp);
|
|
tree t = satisfy (TREE_TYPE (exp), chain);
|
|
SATISFY (d);
|
|
/* It is possible that one of the above satisfy calls recursively
|
|
caused exp to be satisfied, in which case we're done. */
|
|
if (TREE_CODE (exp) != LANG_TYPE)
|
|
return exp;
|
|
TREE_TYPE (exp) = t;
|
|
TYPE_DOMAIN (exp) = d;
|
|
if (!LOOKUP_ONLY)
|
|
exp = smash_dummy_type (exp);
|
|
}
|
|
break;
|
|
case ARRAY_TYPE:
|
|
SATISFY (TREE_TYPE (exp));
|
|
SATISFY (TYPE_DOMAIN (exp));
|
|
SATISFY (TYPE_ATTRIBUTES (exp));
|
|
if (!LOOKUP_ONLY)
|
|
CH_TYPE_NONVALUE_P (exp) = CH_TYPE_NONVALUE_P (TREE_TYPE (exp));
|
|
if (!TYPE_SIZE (exp) && !LOOKUP_ONLY)
|
|
exp = layout_chill_array_type (exp);
|
|
break;
|
|
case FUNCTION_TYPE:
|
|
SATISFY (TREE_TYPE (exp));
|
|
if (TREE_CODE_CLASS (TREE_CODE (TREE_TYPE (exp))) != 't'
|
|
&& !LOOKUP_ONLY && TREE_CODE (TREE_TYPE (exp)) != ERROR_MARK)
|
|
{
|
|
error ("RETURNS spec with invalid mode");
|
|
TREE_TYPE (exp) = error_mark_node;
|
|
}
|
|
satisfy_list_values (TYPE_ARG_TYPES (exp), chain);
|
|
if (!TYPE_SIZE (exp) && !LOOKUP_ONLY)
|
|
layout_type (exp);
|
|
break;
|
|
case ENUMERAL_TYPE:
|
|
if (TYPE_SIZE (exp) == NULL_TREE && !LOOKUP_ONLY)
|
|
{ tree pair;
|
|
/* FIXME: Should this use satisfy_decl? */
|
|
for (pair = TYPE_VALUES (exp); pair; pair = TREE_CHAIN (pair))
|
|
SATISFY (DECL_INITIAL (TREE_VALUE (pair)));
|
|
layout_enum (exp);
|
|
}
|
|
break;
|
|
case INTEGER_TYPE:
|
|
SATISFY (TYPE_MIN_VALUE (exp));
|
|
SATISFY (TYPE_MAX_VALUE (exp));
|
|
if (TREE_TYPE (exp) != NULL_TREE)
|
|
{ /* A range type */
|
|
if (TREE_TYPE (exp) != ridpointers[(int) RID_RANGE]
|
|
&& TREE_TYPE (exp) != ridpointers[(int) RID_BIN]
|
|
&& TREE_TYPE (exp) != string_index_type_dummy)
|
|
SATISFY (TREE_TYPE (exp));
|
|
if (!TYPE_SIZE (exp) && !LOOKUP_ONLY)
|
|
exp = layout_chill_range_type (exp, 1);
|
|
}
|
|
break;
|
|
case POINTER_TYPE:
|
|
case REFERENCE_TYPE:
|
|
if (LOOKUP_ONLY)
|
|
SATISFY (TREE_TYPE (exp));
|
|
else
|
|
{
|
|
struct decl_chain *link;
|
|
int already_seen = 0;
|
|
for (link = chain; ; link = link->prev)
|
|
{
|
|
if (link == NULL)
|
|
{
|
|
struct decl_chain new_link;
|
|
new_link.decl = exp;
|
|
new_link.prev = chain;
|
|
TREE_TYPE (exp) = satisfy (TREE_TYPE (exp), &new_link);
|
|
break;
|
|
}
|
|
else if (link->decl == exp)
|
|
{
|
|
already_seen = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!TYPE_SIZE (exp))
|
|
{
|
|
layout_type (exp);
|
|
if (TREE_CODE (exp) == REFERENCE_TYPE)
|
|
CH_NOVELTY (exp) = CH_NOVELTY (TREE_TYPE (exp));
|
|
if (! already_seen)
|
|
{
|
|
tree valtype = TREE_TYPE (exp);
|
|
if (TREE_CODE_CLASS (TREE_CODE (valtype)) != 't')
|
|
{
|
|
if (TREE_CODE (valtype) != ERROR_MARK)
|
|
error ("operand to REF is not a mode");
|
|
TREE_TYPE (exp) = error_mark_node;
|
|
return error_mark_node;
|
|
}
|
|
else if (TREE_CODE (exp) == POINTER_TYPE
|
|
&& TYPE_POINTER_TO (valtype) == NULL)
|
|
TYPE_POINTER_TO (valtype) = exp;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case RECORD_TYPE:
|
|
{
|
|
/* FIXME: detected errors in here will be printed as
|
|
often as this sequence runs. Find another way or
|
|
place to print the errors. */
|
|
/* if we have an ACCESS or TEXT mode we have to set
|
|
maximum_field_alignment to 0 to fit with runtime
|
|
system, even when we compile with -fpack. */
|
|
unsigned int save_maximum_field_alignment = maximum_field_alignment;
|
|
|
|
if (CH_IS_ACCESS_MODE (exp) || CH_IS_TEXT_MODE (exp))
|
|
maximum_field_alignment = 0;
|
|
|
|
for (decl = TYPE_FIELDS (exp); decl; decl = TREE_CHAIN (decl))
|
|
{
|
|
SATISFY (TREE_TYPE (decl));
|
|
if (!LOOKUP_ONLY)
|
|
{
|
|
/* if we have a UNION_TYPE here (variant structure), check for
|
|
non-value mode in it. This is not allowed (Z.200/pg. 33) */
|
|
if (TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE &&
|
|
CH_TYPE_NONVALUE_P (TREE_TYPE (decl)))
|
|
{
|
|
error ("field with non-value mode in variant structure not allowed");
|
|
TREE_TYPE (decl) = error_mark_node;
|
|
}
|
|
/* RECORD_TYPE gets the non-value property if one of the
|
|
fields has the non-value property */
|
|
CH_TYPE_NONVALUE_P (exp) |= CH_TYPE_NONVALUE_P (TREE_TYPE (decl));
|
|
}
|
|
if (TREE_CODE (decl) == CONST_DECL)
|
|
{
|
|
SATISFY (DECL_INITIAL (decl));
|
|
if (!LOOKUP_ONLY)
|
|
{
|
|
if (CH_IS_BUFFER_MODE (exp) || CH_IS_EVENT_MODE (exp))
|
|
DECL_INITIAL (decl)
|
|
= check_queue_size (DECL_INITIAL (decl));
|
|
else if (CH_IS_TEXT_MODE (exp) &&
|
|
DECL_NAME (decl) == get_identifier ("__textlength"))
|
|
DECL_INITIAL (decl)
|
|
= check_text_length (DECL_INITIAL (decl));
|
|
}
|
|
}
|
|
else if (TREE_CODE (decl) == FIELD_DECL)
|
|
{
|
|
SATISFY (DECL_INITIAL (decl));
|
|
}
|
|
}
|
|
satisfy_list (TYPE_TAG_VALUES (exp), chain);
|
|
if (!TYPE_SIZE (exp) && !LOOKUP_ONLY)
|
|
exp = layout_chill_struct_type (exp);
|
|
maximum_field_alignment = save_maximum_field_alignment;
|
|
|
|
/* perform some checks on nonvalue modes, they are record_mode's */
|
|
if (!LOOKUP_ONLY)
|
|
{
|
|
if (CH_IS_BUFFER_MODE (exp))
|
|
{
|
|
tree elemmode = buffer_element_mode (exp);
|
|
if (elemmode != NULL_TREE && CH_TYPE_NONVALUE_P (elemmode))
|
|
{
|
|
error ("buffer element mode must not have non-value property");
|
|
invalidate_buffer_element_mode (exp);
|
|
}
|
|
}
|
|
else if (CH_IS_ACCESS_MODE (exp))
|
|
{
|
|
tree recordmode = access_recordmode (exp);
|
|
if (recordmode != NULL_TREE && CH_TYPE_NONVALUE_P (recordmode))
|
|
{
|
|
error ("recordmode must not have the non-value property");
|
|
invalidate_access_recordmode (exp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case SET_TYPE:
|
|
SATISFY (TYPE_DOMAIN (exp));
|
|
if (!TYPE_SIZE (exp) && !LOOKUP_ONLY)
|
|
exp = layout_powerset_type (exp);
|
|
break;
|
|
case UNION_TYPE:
|
|
for (decl = TYPE_FIELDS (exp); decl; decl = TREE_CHAIN (decl))
|
|
{
|
|
SATISFY (TREE_TYPE (decl));
|
|
if (!LOOKUP_ONLY)
|
|
CH_TYPE_NONVALUE_P (exp) |= CH_TYPE_NONVALUE_P (TREE_TYPE (decl));
|
|
}
|
|
if (!TYPE_SIZE (exp) && !LOOKUP_ONLY)
|
|
exp = layout_chill_variants (exp);
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
}
|
|
return exp;
|
|
}
|