📄 satisfy.c
字号:
/* Name-satisfaction for GNU Chill compiler. Copyright (C) 1993, 1998 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe 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 declaration */tree satisfy PROTO((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 voidcycle_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 ..."); }}treesafe_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)); 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 (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 (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;}treesatisfy_decl (decl, lookup_only) tree decl; int lookup_only;{ return safe_satisfy_decl (decl, lookup_only ? &dummy_chain : NULL);}static voidsatisfy_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 voidsatisfy_list_values (exp, chain) register tree exp; struct decl_chain *chain;{ for (; exp != NULL_TREE; exp = TREE_CHAIN (exp)) { SATISFY (TREE_VALUE (exp)); }}treesatisfy (exp, chain) tree exp; struct decl_chain *chain;{ int arg_length; int i; tree decl; if (exp == NULL_TREE) return NULL_TREE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -