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,7 +232,8 @@ extern tree parser_build_binary_op PARAMS ((enum tree_code, ...@@ -233,7 +232,8 @@ 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 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, extern tree build_modify_expr PARAMS ((tree, enum tree_code,
tree)); tree));
extern void store_init_value PARAMS ((tree, tree)); extern void store_init_value PARAMS ((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));
......
...@@ -3867,6 +3867,24 @@ build_c_cast (type, expr) ...@@ -3867,6 +3867,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
...@@ -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