diff mbox

[C] Fix PR44257

Message ID CAAgBjMkCciA23CXhWTYRGjR+VKP2-9b00KwKN8Fnszr0gGpbEA@mail.gmail.com
State New
Headers show

Commit Message

Prathamesh Kulkarni June 19, 2015, 2:47 p.m. UTC
Hi,
C FE rejects incomplete type for expression in typeof.

struct foo;
struct foo *p;
typeof (struct foo) *q;  // accepted
typeof (*p) *q;  // error: dereferencing pointer to incomplete type.

The attached patch tries to fix it.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
OK for trunk if testing passes ?

Thank you,
Prathamesh
2015-06-19  Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>

	PR c/44257
	* c-typeck.c (build_indirect_ref): Add check !in_typeof before reporting incomplete type error.
	* gcc.dg/pr44257: New test-case.

Comments

Joseph Myers June 19, 2015, 3:34 p.m. UTC | #1
On Fri, 19 Jun 2015, Prathamesh Kulkarni wrote:

> Hi,
> C FE rejects incomplete type for expression in typeof.
> 
> struct foo;
> struct foo *p;
> typeof (struct foo) *q;  // accepted
> typeof (*p) *q;  // error: dereferencing pointer to incomplete type.
> 
> The attached patch tries to fix it.
> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
> OK for trunk if testing passes ?

Using in_typeof here seems dubious - that would also apply to more 
complicated expressions inside typeof where the value (nested inside some 
larger expression inside typeof) gets used and the code is invalid for 
that reason, not just to direct use of typeof (incomplete).

As noted in bug 36941, what's valid for expressions of incomplete types is 
obscure.  However, my inclination is that the result of such a dereference 
should be valid if immediately passed to unary '&', not just inside 
typeof; that is:

struct foo;
struct foo *p;
void f(void) { &*p; }

should be valid code.  (There's the exception that if the type is 
*unqualified* void it's not valid in C90.)

That is, the error should not be at the point of dereference; it should be 
when the object of incomplete type is used.  Such errors already exist 
(after all, they apply equally well when you're using a variable declared 
with the incomplete type).  There may, however, be issues in cases where 
the conversion from lvalue to rvalue occurs but the value isn't used: the 
case where "*p;" is an expression statement, and the case where it's cast 
to (possibly qualified) void.  Expression statements get diagnosed.  I'd 
say that, as per bug 36941, casts from non-void incomplete types to void 
types should be diagnosed (although this is undefined behavior rather than 
a constraint violation).

Thus: the in_typeof change would, I think, affect typeof ((void) *p), 
which would be correctly diagnosed at present.  What would be correct, to 
avoid losing such a diagnostic while also (a) correctly allowing &*p and 
(b) causing casts of variables of non-void incomplete types to void types 
to be rejected as per bug 36941, would be to remove the diagnostic for the 
dereference (or replace it by a warning) and add one for the casts, along 
with tests for all these cases.
diff mbox

Patch

diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 636e0bb..5dbbea7 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2389,7 +2389,7 @@  build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
 
 	  ref = build1 (INDIRECT_REF, t, pointer);
 
-	  if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
+	  if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE && !in_typeof)
 	    {
 	      if (!C_TYPE_ERROR_REPORTED (TREE_TYPE (ptr)))
 		{
diff --git a/gcc/testsuite/gcc.dg/pr44257.c b/gcc/testsuite/gcc.dg/pr44257.c
new file mode 100644
index 0000000..9657d2a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr44257.c
@@ -0,0 +1,5 @@ 
+/* { dg-do compile } */
+
+struct foo;
+struct foo *p;
+__typeof (*p) *q;