📄 check-init.c
字号:
}/* Check for (un)initialized local variables in EXP.*/static voidcheck_init (exp, before) tree exp; words before;{ tree tmp; again: switch (TREE_CODE (exp)) { case VAR_DECL: if (! FIELD_STATIC (exp) && DECL_NAME (exp) != NULL_TREE) { int index = DECL_BIT_INDEX (exp); if (index >= 0 && ! SET_P (before, index)) {#if 1 parse_error_context (wfl, "Variable `%s' may not have been initialized" , IDENTIFIER_POINTER (DECL_NAME (exp)));#else error_with_decl (exp, "variable may be used uninitialized");#endif /* Suppress further errors. */ DECL_BIT_INDEX (exp) = -1; } } break; case MODIFY_EXPR: tmp = TREE_OPERAND (exp, 0); if (TREE_CODE (tmp) == VAR_DECL && ! FIELD_STATIC (tmp)) { int index; check_init (TREE_OPERAND (exp, 1), before); index = DECL_BIT_INDEX (tmp); if (index >= 0) SET_BIT (before, index); /* Minor optimization. See comment for start_current_locals. */ if (index >= start_current_locals && index == num_current_locals - 1) { num_current_locals--; DECL_BIT_INDEX (tmp) = -1; } break; } else goto binop; case BLOCK: if (BLOCK_EXPR_BODY (exp)) { tree decl = BLOCK_EXPR_DECLS (exp); int words_needed; word* tmp; int i; int save_start_current_locals = start_current_locals; int save_num_current_words = num_current_words; start_current_locals = num_current_locals; for (; decl != NULL_TREE; decl = TREE_CHAIN (decl)) { DECL_BIT_INDEX (decl) = num_current_locals++; } words_needed = WORDS_NEEDED (num_current_locals); if (words_needed > num_current_words) { tmp = ALLOC_WORDS (words_needed); COPY (tmp, before); num_current_words = words_needed; } else tmp = before; for (i = start_current_locals; i < num_current_locals; i++) CLEAR_BIT (tmp, i); check_init (BLOCK_EXPR_BODY (exp), tmp); num_current_locals = start_current_locals; start_current_locals = save_start_current_locals; if (tmp != before) { num_current_words = save_num_current_words; COPY (before, tmp); FREE_WORDS (tmp); } } break; case LOOP_EXPR: { struct alternatives alt; BEGIN_ALTERNATIVES (before, alt); alt.block = exp; check_init (TREE_OPERAND (exp, 0), before); done_alternative (before, &alt); END_ALTERNATIVES (before, alt); return; } case EXIT_EXPR: { struct alternatives *alt = alternatives; words tmp = ALLOC_WORDS (2 * num_current_words); words when_true = tmp; words when_false = tmp + num_current_words;#ifdef ENABLE_CHECKING if (TREE_CODE (alt->block) != LOOP_EXPR) fatal ("internal error in check-init: EXIT_EXPR not in LOOP_EXPR");#endif check_bool_init (TREE_OPERAND (exp, 0), before, when_false, when_true); done_alternative (when_true, alt); COPY (before, when_false); FREE_WORDS (tmp); return; } case LABELED_BLOCK_EXPR: { struct alternatives alt; BEGIN_ALTERNATIVES (before, alt); alt.block = exp; if (LABELED_BLOCK_BODY (exp)) check_init (LABELED_BLOCK_BODY (exp), before); done_alternative (before, &alt); END_ALTERNATIVES (before, alt); return; } case EXIT_BLOCK_EXPR: { tree block = TREE_OPERAND (exp, 0); struct alternatives *alt = alternatives; while (alt->block != block) alt = alt->outer; done_alternative (before, alt); SET_ALL (before); return; } case SWITCH_EXPR: { struct alternatives alt; check_init (TREE_OPERAND (exp, 0), before); BEGIN_ALTERNATIVES (before, alt); alt.saved = ALLOC_WORDS (num_current_words); COPY (alt.saved, before); alt.block = exp; check_init (TREE_OPERAND (exp, 1), before); done_alternative (before, &alt); FREE_WORDS (alt.saved); END_ALTERNATIVES (before, alt); return; } case CASE_EXPR: case DEFAULT_EXPR: { int i; struct alternatives *alt = alternatives; while (TREE_CODE (alt->block) != SWITCH_EXPR) alt = alt->outer; COPYN (before, alt->saved, WORDS_NEEDED (alt->num_locals)); for (i = alt->num_locals; i < num_current_locals; i++) CLEAR_BIT (before, i); break; } case CLEANUP_POINT_EXPR: { struct alternatives alt; BEGIN_ALTERNATIVES (before, alt); CLEAR_ALL (alt.combined); check_init (TREE_OPERAND (exp, 0), before); UNION (alt.combined, alt.combined, before); END_ALTERNATIVES (before, alt); } return; case WITH_CLEANUP_EXPR: { struct alternatives *alt = alternatives; #ifdef ENABLE_CHECKING if (TREE_CODE (alt->block) != CLEANUP_POINT_EXPR) fatal ("internal error in check-init: WITH_CLEANUP_EXPR not in CLEANUP_POINT_EXPR");#endif check_init (TREE_OPERAND (exp, 0), before); UNION (alt->combined, alt->combined, before); check_init (TREE_OPERAND (exp, 2), alt->combined); return; } case TRY_EXPR: { tree try_clause = TREE_OPERAND (exp, 0); tree clause = TREE_OPERAND (exp, 1); words save = ALLOC_WORDS (num_current_words); words tmp = ALLOC_WORDS (num_current_words); struct alternatives alt; BEGIN_ALTERNATIVES (before, alt); COPY (save, before); COPY (tmp, save); check_init (try_clause, tmp); done_alternative (tmp, &alt); for ( ; clause != NULL_TREE; clause = TREE_CHAIN (clause)) { tree catch_clause = TREE_OPERAND (clause, 0); COPY (tmp, save); check_init (catch_clause, tmp); done_alternative (tmp, &alt); } FREE_WORDS (tmp); FREE_WORDS (save); END_ALTERNATIVES (before, alt); } return; case TRY_FINALLY_EXPR: { words tmp = ALLOC_WORDS (num_current_words); COPY (tmp, before); check_init (TREE_OPERAND (exp, 0), tmp); check_init (TREE_OPERAND (exp, 1), before); FREE_WORDS (tmp); } return; case RETURN_EXPR: case THROW_EXPR: if (TREE_OPERAND (exp, 0)) check_init (TREE_OPERAND (exp, 0), before); goto never_continues; case ERROR_MARK: never_continues: SET_ALL (before); return; case COND_EXPR: case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: { words tmp = ALLOC_WORDS (2 * num_current_words); words when_true = tmp; words when_false = tmp + num_current_words; check_bool_init (exp, before, when_false, when_true); INTERSECT (before, when_false, when_true); FREE_WORDS (tmp); } break; case UNARY_PLUS_EXPR: case NEGATE_EXPR: case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: case TRUTH_XOR_EXPR: case TRUTH_NOT_EXPR: case BIT_NOT_EXPR: case CONVERT_EXPR: case COMPONENT_REF: case NOP_EXPR: case FLOAT_EXPR: case FIX_TRUNC_EXPR: case INDIRECT_REF: case ADDR_EXPR: case SAVE_EXPR: case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: case NON_LVALUE_EXPR: case INSTANCEOF_EXPR: /* Avoid needless recursion. */ exp = TREE_OPERAND (exp, 0); goto again; case COMPOUND_EXPR: case PLUS_EXPR: case MINUS_EXPR: case MULT_EXPR: case TRUNC_DIV_EXPR: case TRUNC_MOD_EXPR: case RDIV_EXPR: case LSHIFT_EXPR: case RSHIFT_EXPR: case URSHIFT_EXPR: case BIT_AND_EXPR: case BIT_XOR_EXPR: case BIT_IOR_EXPR: case EQ_EXPR: case NE_EXPR: case GT_EXPR: case GE_EXPR: case LT_EXPR: case LE_EXPR: case ARRAY_REF: binop: check_init (TREE_OPERAND (exp, 0), before); /* Avoid needless recursion, especially for COMPOUND_EXPR. */ exp = TREE_OPERAND (exp, 1); goto again; case PARM_DECL: case RESULT_DECL: case FUNCTION_DECL: case INTEGER_CST: case REAL_CST: case STRING_CST: break; case NEW_CLASS_EXPR: case CALL_EXPR: { tree func = TREE_OPERAND (exp, 0); tree x = TREE_OPERAND (exp, 1); if (TREE_CODE (func) == ADDR_EXPR) func = TREE_OPERAND (func, 0); check_init (func, before); for ( ; x != NULL_TREE; x = TREE_CHAIN (x)) check_init (TREE_VALUE (x), before); if (func == throw_node) goto never_continues; } break; case NEW_ARRAY_INIT: { tree x = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); for ( ; x != NULL_TREE; x = TREE_CHAIN (x)) check_init (TREE_VALUE (x), before); } break; case EXPR_WITH_FILE_LOCATION: { char *saved_input_filename = input_filename; tree saved_wfl = wfl; tree body = EXPR_WFL_NODE (exp); int saved_lineno = lineno; if (body == empty_stmt_node) break; wfl = exp; input_filename = EXPR_WFL_FILENAME (exp); lineno = EXPR_WFL_LINENO (exp); check_init (body, before); input_filename = saved_input_filename; lineno = saved_lineno; wfl = saved_wfl; } break; default: fatal ("internal error in check-init: tree code not implemented: %s", tree_code_name [(int) TREE_CODE (exp)]); }}voidcheck_for_initialization (body) tree body;{ word before = 0; check_init (body, &before);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -