aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c/c-typeck.c11
-rw-r--r--gcc/cfgexpand.c43
-rw-r--r--gcc/cp/typeck.c7
-rw-r--r--gcc/gimplify.c9
-rw-r--r--gcc/testsuite/c-c++-common/pr100785.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr48552-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr48552-2.c4
7 files changed, 82 insertions, 17 deletions
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 845d50f..77de881 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -5034,8 +5034,17 @@ c_mark_addressable (tree exp, bool array_ref_p)
&& TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
return true;
- /* FALLTHRU */
+ x = TREE_OPERAND (x, 0);
+ break;
+
case COMPONENT_REF:
+ if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
+ {
+ error ("cannot take address of bit-field %qD",
+ TREE_OPERAND (x, 1));
+ return false;
+ }
+ /* FALLTHRU */
case ADDR_EXPR:
case ARRAY_REF:
case REALPART_EXPR:
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 39e5b04..6394cfd 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3082,6 +3082,7 @@ expand_asm_stmt (gasm *stmt)
unsigned ninputs = gimple_asm_ninputs (stmt);
unsigned nlabels = gimple_asm_nlabels (stmt);
unsigned i;
+ bool error_seen = false;
/* ??? Diagnose during gimplification? */
if (ninputs + noutputs + nlabels > MAX_RECOG_OPERANDS)
@@ -3140,6 +3141,7 @@ expand_asm_stmt (gasm *stmt)
{
/* ??? Diagnose during gimplification? */
error ("unknown register name %qs in %<asm%>", regname);
+ error_seen = true;
}
else if (j == -4)
{
@@ -3202,7 +3204,10 @@ expand_asm_stmt (gasm *stmt)
&& REG_P (DECL_RTL (output_tvec[j]))
&& HARD_REGISTER_P (DECL_RTL (output_tvec[j]))
&& output_hregno == REGNO (DECL_RTL (output_tvec[j])))
- error ("invalid hard register usage between output operands");
+ {
+ error ("invalid hard register usage between output operands");
+ error_seen = true;
+ }
/* Verify matching constraint operands use the same hard register
and that the non-matching constraint operands do not use the same
@@ -3225,13 +3230,19 @@ expand_asm_stmt (gasm *stmt)
}
if (i == match
&& output_hregno != input_hregno)
- error ("invalid hard register usage between output operand "
- "and matching constraint operand");
+ {
+ error ("invalid hard register usage between output "
+ "operand and matching constraint operand");
+ error_seen = true;
+ }
else if (early_clobber_p
&& i != match
&& output_hregno == input_hregno)
- error ("invalid hard register usage between earlyclobber "
- "operand and input operand");
+ {
+ error ("invalid hard register usage between "
+ "earlyclobber operand and input operand");
+ error_seen = true;
+ }
}
}
@@ -3307,7 +3318,10 @@ expand_asm_stmt (gasm *stmt)
op = validize_mem (op);
if (! allows_reg && !MEM_P (op))
- error ("output number %d not directly addressable", i);
+ {
+ error ("output number %d not directly addressable", i);
+ error_seen = true;
+ }
if ((! allows_mem && MEM_P (op) && GET_MODE (op) != BLKmode)
|| GET_CODE (op) == CONCAT)
{
@@ -3347,6 +3361,19 @@ expand_asm_stmt (gasm *stmt)
inout_opnum.safe_push (i);
}
+ const char *str = gimple_asm_string (stmt);
+ if (error_seen)
+ {
+ ninputs = 0;
+ noutputs = 0;
+ inout_opnum.truncate (0);
+ output_rvec.truncate (0);
+ clobber_rvec.truncate (0);
+ constraints.truncate (0);
+ CLEAR_HARD_REG_SET (clobbered_regs);
+ str = "";
+ }
+
auto_vec<rtx, MAX_RECOG_OPERANDS> input_rvec;
auto_vec<machine_mode, MAX_RECOG_OPERANDS> input_mode;
@@ -3405,7 +3432,7 @@ expand_asm_stmt (gasm *stmt)
}
/* For in-out operands, copy output rtx to input rtx. */
- unsigned ninout = inout_opnum.length();
+ unsigned ninout = inout_opnum.length ();
for (i = 0; i < ninout; i++)
{
int j = inout_opnum[i];
@@ -3459,7 +3486,7 @@ expand_asm_stmt (gasm *stmt)
rtx body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
: GET_MODE (output_rvec[0])),
- ggc_strdup (gimple_asm_string (stmt)),
+ ggc_strdup (str),
"", 0, argvec, constraintvec,
labelvec, locus);
MEM_VOLATILE_P (body) = gimple_asm_volatile_p (stmt);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index dbb2370..5a9331b 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -7119,9 +7119,14 @@ cxx_mark_addressable (tree exp, bool array_ref_p)
&& TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
return true;
+ x = TREE_OPERAND (x, 0);
+ break;
+
+ case COMPONENT_REF:
+ if (bitfield_p (x))
+ error ("attempt to take address of bit-field");
/* FALLTHRU */
case ADDR_EXPR:
- case COMPONENT_REF:
case ARRAY_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 2606998..41bae9c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6323,12 +6323,14 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
if (!allows_reg && allows_mem)
mark_addressable (TREE_VALUE (link));
+ tree orig = TREE_VALUE (link);
tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
is_inout ? is_gimple_min_lval : is_gimple_lvalue,
fb_lvalue | fb_mayfail);
if (tret == GS_ERROR)
{
- error ("invalid lvalue in %<asm%> output %d", i);
+ if (orig != error_mark_node)
+ error ("invalid lvalue in %<asm%> output %d", i);
ret = tret;
}
@@ -6523,8 +6525,9 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
mark_addressable (TREE_VALUE (link));
if (tret == GS_ERROR)
{
- error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location),
- "memory input %d is not directly addressable", i);
+ if (inputv != error_mark_node)
+ error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location),
+ "memory input %d is not directly addressable", i);
ret = tret;
}
}
diff --git a/gcc/testsuite/c-c++-common/pr100785.c b/gcc/testsuite/c-c++-common/pr100785.c
new file mode 100644
index 0000000..37ff0aa
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr100785.c
@@ -0,0 +1,21 @@
+/* PR inline-asm/100785 */
+
+struct S { int a : 1; };
+
+void
+foo (struct S *x)
+{
+ __asm__ ("" : "+m" (x->a)); /* { dg-error "address of bit-field" } */
+}
+
+void
+bar (struct S *x)
+{
+ __asm__ ("" : "=m" (x->a)); /* { dg-error "address of bit-field" } */
+}
+
+void
+baz (struct S *x)
+{
+ __asm__ ("" : : "m" (x->a)); /* { dg-error "address of bit-field" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr48552-1.c b/gcc/testsuite/gcc.dg/pr48552-1.c
index 11ee401..4cd7c59 100644
--- a/gcc/testsuite/gcc.dg/pr48552-1.c
+++ b/gcc/testsuite/gcc.dg/pr48552-1.c
@@ -15,7 +15,7 @@ f2 (void *x)
{
__asm volatile ("" : "=r" (*x)); /* { dg-warning "dereferencing" "deref" } */
} /* { dg-error "invalid use of void expression" "void expr" { target *-*-* } .-1 } */
- /* { dg-error "invalid lvalue in 'asm' output 0" "invalid lvalue" { target *-*-* } .-2 } */
+
void
f3 (void *x)
{
@@ -39,7 +39,7 @@ f6 (void *x)
{
__asm volatile ("" : "=g" (*x)); /* { dg-warning "dereferencing" "deref" } */
} /* { dg-error "invalid use of void expression" "void expr" { target *-*-* } .-1 } */
- /* { dg-error "invalid lvalue in 'asm' output 0" "invalid lvalue" { target *-*-* } .-2 } */
+
void
f7 (struct S *x)
{
diff --git a/gcc/testsuite/gcc.dg/pr48552-2.c b/gcc/testsuite/gcc.dg/pr48552-2.c
index 2d2a00c..e22600a 100644
--- a/gcc/testsuite/gcc.dg/pr48552-2.c
+++ b/gcc/testsuite/gcc.dg/pr48552-2.c
@@ -15,7 +15,7 @@ f2 (void *x)
{
__asm ("" : "=r" (*x)); /* { dg-warning "dereferencing" "deref" } */
} /* { dg-error "invalid use of void expression" "void expr" { target *-*-* } .-1 } */
- /* { dg-error "invalid lvalue in 'asm' output 0" "invalid lvalue" { target *-*-* } .-2 } */
+
void
f3 (void *x)
{
@@ -39,7 +39,7 @@ f6 (void *x)
{
__asm ("" : "=g" (*x)); /* { dg-warning "dereferencing" "deref" } */
} /* { dg-error "invalid use of void expression" "void expr" { target *-*-* } .-1 } */
- /* { dg-error "invalid lvalue in 'asm' output 0" "invalid lvalue" { target *-*-* } .-2 } */
+
void
f7 (struct S *x)
{