Commit 15b732b2 by Neil Booth Committed by Neil Booth

c-common.c (finish_label_expr): New function, lifted from from cp/semantics.c.

	* 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.

From-SVN: r41959
parent 8e93d446
2001-05-11 Neil Booth <neil@daikokuya.demon.co.uk>
* 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 <aoliva@redhat.com> 2001-05-11 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/t-mn10300 (dp-bit.c, fp-bit.c): Don't define * config/mn10300/t-mn10300 (dp-bit.c, fp-bit.c): Don't define
......
...@@ -4193,6 +4193,39 @@ c_add_case_label (cases, cond, low_value, high_value) ...@@ -4193,6 +4193,39 @@ c_add_case_label (cases, cond, low_value, high_value)
return case_label; 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 /* 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 parameter allows this function to be used as a GC-marking
function. */ function. */
......
...@@ -783,6 +783,12 @@ extern tree c_add_case_label PARAMS ((splay_tree, ...@@ -783,6 +783,12 @@ extern tree c_add_case_label PARAMS ((splay_tree,
extern tree build_function_call PARAMS ((tree, 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 /* 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 after the file has been completely parsed. The argument will be
the GLOBAL_NAMESPACE in C++, or the list of top-level declarations the GLOBAL_NAMESPACE in C++, or the list of top-level declarations
......
...@@ -493,18 +493,7 @@ unary_expr: ...@@ -493,18 +493,7 @@ unary_expr:
overflow_warning ($$); } overflow_warning ($$); }
/* Refer to the address of a label as a pointer. */ /* Refer to the address of a label as a pointer. */
| ANDAND identifier | ANDAND identifier
{ tree label = lookup_label ($2); { $$ = finish_label_address_expr ($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;
}
}
/* This seems to be impossible on some machines, so let's turn it off. /* 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. You can use __builtin_next_arg to find the anonymous stack args.
| '&' ELLIPSIS | '&' ELLIPSIS
...@@ -552,15 +541,7 @@ alignof: ...@@ -552,15 +541,7 @@ alignof:
cast_expr: cast_expr:
unary_expr unary_expr
| '(' typename ')' cast_expr %prec UNARY | '(' typename ')' cast_expr %prec UNARY
{ tree type; { $$ = c_cast_expr ($2, $4); }
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); }
; ;
expr_no_commas: expr_no_commas:
...@@ -2401,26 +2382,7 @@ stmt: ...@@ -2401,26 +2382,7 @@ stmt:
$$ = c_expand_return ($2); } $$ = c_expand_return ($2); }
| ASM_KEYWORD maybe_type_qual '(' expr ')' ';' | ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
{ stmt_count++; { stmt_count++;
STRIP_NOPS ($4); $$ = simple_asm_stmt ($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;
}
}
/* This is the case with just output operands. */ /* This is the case with just output operands. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';' | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
{ stmt_count++; { stmt_count++;
......
...@@ -187,7 +187,6 @@ extern void implicit_decl_warning PARAMS ((tree)); ...@@ -187,7 +187,6 @@ extern void implicit_decl_warning PARAMS ((tree));
extern int in_parm_level_p PARAMS ((void)); extern int in_parm_level_p PARAMS ((void));
extern void keep_next_level PARAMS ((void)); extern void keep_next_level PARAMS ((void));
extern int kept_level_p 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 PARAMS ((tree));
extern tree lookup_name_current_level PARAMS ((tree)); extern tree lookup_name_current_level PARAMS ((tree));
extern tree lookup_name_current_level_global PARAMS ((tree)); extern tree lookup_name_current_level_global PARAMS ((tree));
...@@ -233,6 +232,7 @@ extern tree parser_build_binary_op PARAMS ((enum tree_code, ...@@ -233,6 +232,7 @@ extern tree parser_build_binary_op PARAMS ((enum tree_code,
extern void readonly_warning PARAMS ((tree, const char *)); extern void readonly_warning PARAMS ((tree, const char *));
extern tree build_conditional_expr PARAMS ((tree, tree, tree)); extern tree build_conditional_expr PARAMS ((tree, tree, tree));
extern tree build_compound_expr PARAMS ((tree)); extern tree build_compound_expr PARAMS ((tree));
extern tree c_cast_expr PARAMS ((tree, tree));
extern tree build_c_cast PARAMS ((tree, tree)); extern tree build_c_cast PARAMS ((tree, tree));
extern tree build_modify_expr PARAMS ((tree, enum tree_code, extern tree build_modify_expr PARAMS ((tree, enum tree_code,
tree)); tree));
...@@ -251,6 +251,7 @@ extern void pedwarn_c99 PARAMS ((const char *, ...)) ...@@ -251,6 +251,7 @@ extern void pedwarn_c99 PARAMS ((const char *, ...))
ATTRIBUTE_PRINTF_1; ATTRIBUTE_PRINTF_1;
extern tree c_start_case PARAMS ((tree)); extern tree c_start_case PARAMS ((tree));
extern void c_finish_case PARAMS ((void)); extern void c_finish_case PARAMS ((void));
extern tree simple_asm_stmt PARAMS ((tree));
extern tree build_asm_stmt PARAMS ((tree, tree, tree, extern tree build_asm_stmt PARAMS ((tree, tree, tree,
tree, tree)); tree, tree));
......
...@@ -3868,6 +3868,24 @@ build_c_cast (type, expr) ...@@ -3868,6 +3868,24 @@ build_c_cast (type, expr)
return value; 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. /* Build an assignment expression of lvalue LHS from value RHS.
MODIFYCODE is the code for a binary operator that we use MODIFYCODE is the code for a binary operator that we use
to combine the old value of LHS with RHS to get the new value. to combine the old value of LHS with RHS to get the new value.
...@@ -6763,6 +6781,33 @@ process_init_element (value) ...@@ -6763,6 +6781,33 @@ process_init_element (value)
constructor_range_stack = 0; 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 /* Build an asm-statement, whose components are a CV_QUALIFIER, a
STRING, some OUTPUTS, some INPUTS, and some CLOBBERS. */ STRING, some OUTPUTS, some INPUTS, and some CLOBBERS. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment