diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b4a3b80aebf..2053f37be47 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2001-05-11 Neil Booth + + * c-common.c (finish_label_expr): New function, lifted from + from cp/semantics.c. + * c-common.h (finish_label_expr, lookup_label): New prototypes. + * c-parse.in: Move 3 blocks of parser code into new functions. + * c-typeck.c (simple_asm_stmt, c_cast_expr): New functions. + * c-tree.h (simple_asm_stmt, c_cast_expr): New prototypes. + (lookup_label): Remove. + 2001-05-11 Alexandre Oliva * config/mn10300/t-mn10300 (dp-bit.c, fp-bit.c): Don't define diff --git a/gcc/c-common.c b/gcc/c-common.c index a1dc31c3160..f037ecc9ae3 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -4193,6 +4193,39 @@ c_add_case_label (cases, cond, low_value, high_value) return case_label; } +/* Finish an expression taking the address of LABEL. Returns an + expression for the address. */ + +tree +finish_label_address_expr (label) + tree label; +{ + tree result; + + if (pedantic) + { + if (c_language == clk_cplusplus) + pedwarn ("ISO C++ forbids taking the address of a label"); + else + pedwarn ("ISO C forbids taking the address of a label"); + } + + label = lookup_label (label); + if (label == NULL_TREE) + result = null_pointer_node; + else + { + TREE_USED (label) = 1; + result = build1 (ADDR_EXPR, ptr_type_node, label); + TREE_CONSTANT (result) = 1; + /* The current function in not necessarily uninlinable. + Computed gotos are incompatible with inlining, but the value + here could be used only in a diagnostic, for example. */ + } + + return result; +} + /* Mark P (a stmt_tree) for GC. The use of a `void *' for the parameter allows this function to be used as a GC-marking function. */ diff --git a/gcc/c-common.h b/gcc/c-common.h index 32d7ec99003..0c2f23a8c23 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -783,6 +783,12 @@ extern tree c_add_case_label PARAMS ((splay_tree, extern tree build_function_call PARAMS ((tree, tree)); +extern tree finish_label_address_expr PARAMS ((tree)); + +/* Same function prototype, but the C and C++ front ends have + different implementations. Used in c-common.c. */ +extern tree lookup_label PARAMS ((tree)); + /* If this variable is defined to a non-NULL value, it will be called after the file has been completely parsed. The argument will be the GLOBAL_NAMESPACE in C++, or the list of top-level declarations diff --git a/gcc/c-parse.in b/gcc/c-parse.in index e91f9ebdf9f..253cb292b66 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -493,18 +493,7 @@ unary_expr: overflow_warning ($$); } /* Refer to the address of a label as a pointer. */ | ANDAND identifier - { tree label = lookup_label ($2); - if (pedantic) - pedwarn ("ISO C forbids `&&'"); - if (label == 0) - $$ = null_pointer_node; - else - { - TREE_USED (label) = 1; - $$ = build1 (ADDR_EXPR, ptr_type_node, label); - TREE_CONSTANT ($$) = 1; - } - } + { $$ = finish_label_address_expr ($2); } /* This seems to be impossible on some machines, so let's turn it off. You can use __builtin_next_arg to find the anonymous stack args. | '&' ELLIPSIS @@ -552,15 +541,7 @@ alignof: cast_expr: unary_expr | '(' typename ')' cast_expr %prec UNARY - { tree type; - int SAVED_warn_strict_prototypes = warn_strict_prototypes; - /* This avoids warnings about unprototyped casts on - integers. E.g. "#define SIG_DFL (void(*)())0". */ - if (TREE_CODE ($4) == INTEGER_CST) - warn_strict_prototypes = 0; - type = groktypename ($2); - warn_strict_prototypes = SAVED_warn_strict_prototypes; - $$ = build_c_cast (type, $4); } + { $$ = c_cast_expr ($2, $4); } ; expr_no_commas: @@ -2401,26 +2382,7 @@ stmt: $$ = c_expand_return ($2); } | ASM_KEYWORD maybe_type_qual '(' expr ')' ';' { stmt_count++; - STRIP_NOPS ($4); - if ((TREE_CODE ($4) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND ($4, 0)) == STRING_CST) - || TREE_CODE ($4) == STRING_CST) - { - if (TREE_CODE ($4) == ADDR_EXPR) - $4 = TREE_OPERAND ($4, 0); - if (TREE_CHAIN ($4)) - $4 = combine_strings ($4); - $$ = add_stmt (build_stmt (ASM_STMT, NULL_TREE, $4, - NULL_TREE, NULL_TREE, - NULL_TREE)); - ASM_INPUT_P ($$) = 1; - } - else - { - error ("argument of `asm' is not a constant string"); - $$ = NULL_TREE; - } - } + $$ = simple_asm_stmt ($4); } /* This is the case with just output operands. */ | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';' { stmt_count++; diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 16ab7adafce..543a310280f 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -187,7 +187,6 @@ extern void implicit_decl_warning PARAMS ((tree)); extern int in_parm_level_p PARAMS ((void)); extern void keep_next_level PARAMS ((void)); extern int kept_level_p PARAMS ((void)); -extern tree lookup_label PARAMS ((tree)); extern tree lookup_name PARAMS ((tree)); extern tree lookup_name_current_level PARAMS ((tree)); extern tree lookup_name_current_level_global PARAMS ((tree)); @@ -233,7 +232,8 @@ extern tree parser_build_binary_op PARAMS ((enum tree_code, extern void readonly_warning PARAMS ((tree, const char *)); extern tree build_conditional_expr PARAMS ((tree, tree, tree)); extern tree build_compound_expr PARAMS ((tree)); -extern tree build_c_cast PARAMS ((tree, tree)); +extern tree c_cast_expr PARAMS ((tree, tree)); +extern tree build_c_cast PARAMS ((tree, tree)); extern tree build_modify_expr PARAMS ((tree, enum tree_code, tree)); extern void store_init_value PARAMS ((tree, tree)); @@ -251,6 +251,7 @@ extern void pedwarn_c99 PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1; extern tree c_start_case PARAMS ((tree)); extern void c_finish_case PARAMS ((void)); +extern tree simple_asm_stmt PARAMS ((tree)); extern tree build_asm_stmt PARAMS ((tree, tree, tree, tree, tree)); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 33ac1169a82..3cbf6c6f3ef 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -3867,6 +3867,24 @@ build_c_cast (type, expr) return value; } + +/* Interpret a cast of expression EXPR to type TYPE. */ +tree +c_cast_expr (type, expr) + tree type, expr; +{ + int saved_wsp = warn_strict_prototypes; + + /* This avoids warnings about unprototyped casts on + integers. E.g. "#define SIG_DFL (void(*)())0". */ + if (TREE_CODE (expr) == INTEGER_CST) + warn_strict_prototypes = 0; + type = groktypename (type); + warn_strict_prototypes = saved_wsp; + + return build_c_cast (type, expr); +} + /* Build an assignment expression of lvalue LHS from value RHS. MODIFYCODE is the code for a binary operator that we use @@ -6763,6 +6781,33 @@ process_init_element (value) constructor_range_stack = 0; } +/* Build a simple asm-statement, from one string literal. */ +tree +simple_asm_stmt (expr) + tree expr; +{ + STRIP_NOPS (expr); + + if (TREE_CODE (expr) == ADDR_EXPR) + expr = TREE_OPERAND (expr, 0); + + if (TREE_CODE (expr) == STRING_CST) + { + tree stmt; + + if (TREE_CHAIN (expr)) + expr = combine_strings (expr); + stmt = add_stmt (build_stmt (ASM_STMT, NULL_TREE, expr, + NULL_TREE, NULL_TREE, + NULL_TREE)); + ASM_INPUT_P (stmt) = 1; + return stmt; + } + + error ("argument of `asm' is not a constant string"); + return NULL_TREE; +} + /* Build an asm-statement, whose components are a CV_QUALIFIER, a STRING, some OUTPUTS, some INPUTS, and some CLOBBERS. */