Bug 36941 - gcc does not reject invalid cast
Summary: gcc does not reject invalid cast
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: unknown
: P3 normal
Target Milestone: 10.0
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid, diagnostic
Depends on:
Blocks:
 
Reported: 2008-07-25 22:15 UTC by Chris Lattner
Modified: 2019-12-06 10:55 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-07-25 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Lattner 2008-07-25 22:15:04 UTC
GCC accepts:
extern struct S x;
void foo() { (void)x; }

But correctly rejects:

extern struct S x;
void foo() { x; }

Comeau rejects both in c99 mode.
Comment 1 jsm-csl@polyomino.org.uk 2008-07-25 22:29:31 UTC
Subject: Re:   New: gcc does not reject invalid cast

On Fri, 25 Jul 2008, sabre at nondot dot org wrote:

> GCC accepts:
> extern struct S x;
> void foo() { (void)x; }

What constraint do you think this violates, or are you just reporting a 
QoI issue for not diagnosing undefined behavior?

Comment 2 Chris Lattner 2008-07-25 22:30:12 UTC
'If the lvalue has an incomplete type and does not have array type, the behavior is 
undefined.'

QoI
Comment 3 Chris Lattner 2008-07-25 22:31:30 UTC
Though that does raise a question.  Does GCC normally emit errors for undefined behavior?  I thought the policy was to insert runtime traps?  If so, doesn't the { x; } case qualify, or does it violate some other constraint?
Comment 4 jsm-csl@polyomino.org.uk 2008-07-25 22:59:28 UTC
Subject: Re:  gcc does not reject invalid cast

On Fri, 25 Jul 2008, sabre at nondot dot org wrote:

> Though that does raise a question.  Does GCC normally emit errors for undefined
> behavior?  I thought the policy was to insert runtime traps?  If so, doesn't
> the { x; } case qualify, or does it violate some other constraint?

What's valid for expressions of incomplete types - including whether the 
cases of undefined behavior here are undefined only at execution or 
undefined as a property of the program (the former being where traps are 
inserted, the latter being where diagnostics are OK) is exceedingly 
obscure.  We do have a bit of guidance in the form of DR 106 allowing the 
dereference of pointers to qualified void in certain cases (note that 
qualified void is an incomplete type other than void).  It doesn't help 
that neither C90 nor C99 got the definition of "lvalue" right.

Comment 5 Chris Lattner 2008-07-26 05:10:03 UTC
Ok, so is it right or wrong? :)
Comment 6 Manuel López-Ibáñez 2008-08-23 02:44:36 UTC
extern struct S x;
void foo() { (void)x; }
void baz() { x ; }

pr36941.c: In function ‘baz’:
pr36941.c:3:1: error: expression statement has incomplete type

Where is the quote about undefined behaviour from?
Comment 7 Eric Gallager 2017-07-25 00:48:23 UTC
(In reply to Chris Lattner from comment #0)
> GCC accepts:
> extern struct S x;
> void foo() { (void)x; }
> 
> But correctly rejects:
> 
> extern struct S x;
> void foo() { x; }
> 

Confirmed. Note that clang diagnoses the first one like this:

$ /sw/opt/llvm-3.1/bin/clang-3.1 -c 36941.c
36941.c:2:20: error: incomplete type 'struct S' where a complete type is required
void foo() { (void)x; }
                   ^
36941.c:1:15: note: forward declaration of 'struct S'
extern struct S x;
              ^
Comment 8 Eric Gallager 2018-04-25 13:02:22 UTC
(In reply to Eric Gallager from comment #7)
> (In reply to Chris Lattner from comment #0)
> > GCC accepts:
> > extern struct S x;
> > void foo() { (void)x; }
> > 
> > But correctly rejects:
> > 
> > extern struct S x;
> > void foo() { x; }
> > 
> 
> Confirmed. Note that clang diagnoses the first one like this:
> 
> $ /sw/opt/llvm-3.1/bin/clang-3.1 -c 36941.c
> 36941.c:2:20: error: incomplete type 'struct S' where a complete type is
> required
> void foo() { (void)x; }
>                    ^
> 36941.c:1:15: note: forward declaration of 'struct S'
> extern struct S x;
>               ^

Same thing with a newer version of clang (5.0). Assuming that since clang still rejects this that this is an accepts-invalid for gcc.
Comment 9 Joseph S. Myers 2019-12-04 23:26:42 UTC
Author: jsm28
Date: Wed Dec  4 23:26:10 2019
New Revision: 278976

URL: https://gcc.gnu.org/viewcvs?rev=278976&root=gcc&view=rev
Log:
Fix C handling of use of lvalues of incomplete types (PR c/36941, PR c/88827).

Bug 88827 points out that GCC should not be rejecting C code that
dereferences a pointer to an incomplete type in the case that uses &*
to take the address of the resulting lvalue, because no constraint is
violated in that case (other than for C90 when the incomplete type is
unqualified void, which we already handle correctly) and as the lvalue
never gets converted to an rvalue there is no undefined behavior
either.

This means that the diagnostic for such a dereference is bogus and
should be removed; if the lvalue gets converted to an rvalue, there
should be an appropriate error later for the use of the incomplete
type.  In most cases, there is, but bug 36941 points out the lack of a
diagnostic when the incomplete (non-void) type gets cast to void
(where a diagnostic seems appropriate for this undefined behavior as a
matter of quality of implementation).

This patch removes the bogus diagnostic (and C_TYPE_ERROR_REPORTED
which was only used in the code that is removed - only that one, bogus
diagnostic had this duplicate suppression, not any of the other, more
legitimate diagnostics for use of incomplete types) and makes
convert_lvalue_to_rvalue call require_complete_type for arguments not
of void types, so that all relevant code paths (possibly except some
for ObjC) get incomplete types diagnosed.  It's possible that this
makes some other checks for incomplete types obsolete, but no attempt
is made to remove any such checks.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

	PR c/36941
	PR c/88827
gcc/c:
	* c-typeck.c (convert_lvalue_to_rvalue): Call
	require_complete_type for arguments not of void types.
	(build_indirect_ref): Do not diagnose dereferencing pointers to
	incomplete types.
	* c-tree.h (C_TYPE_ERROR_REPORTED): Remove.

gcc/testsuite:
	* gcc.dg/lvalue-9.c, gcc.dg/lvalue-10.c: New tests.
	* gcc.dg/array-8.c, gcc.dg/enum-incomplete-1.c,
	gcc.dg/enum-incomplete-3.c, gcc.dg/noncompile/incomplete-3.c,
	gcc.dg/pr48552-1.c, gcc.dg/pr48552-2.c, gcc.dg/pr63543.c,
	gcc.dg/pr69796.c: Update expected diagnostics.

Added:
    trunk/gcc/testsuite/gcc.dg/lvalue-10.c
    trunk/gcc/testsuite/gcc.dg/lvalue-9.c
Modified:
    trunk/gcc/c/ChangeLog
    trunk/gcc/c/c-tree.h
    trunk/gcc/c/c-typeck.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.dg/array-8.c
    trunk/gcc/testsuite/gcc.dg/enum-incomplete-1.c
    trunk/gcc/testsuite/gcc.dg/enum-incomplete-3.c
    trunk/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c
    trunk/gcc/testsuite/gcc.dg/pr48552-1.c
    trunk/gcc/testsuite/gcc.dg/pr48552-2.c
    trunk/gcc/testsuite/gcc.dg/pr63543.c
    trunk/gcc/testsuite/gcc.dg/pr69796.c
Comment 10 Joseph S. Myers 2019-12-04 23:27:48 UTC
Fixed for GCC 10.
Comment 11 Christophe Lyon 2019-12-06 10:55:17 UTC
Author: clyon
Date: Fri Dec  6 10:54:46 2019
New Revision: 279039

URL: https://gcc.gnu.org/viewcvs?rev=279039&root=gcc&view=rev
Log:
[testsuite][aarch64] type_redef_11.c: Update expected diagnostics.

After the fix for PR c/36941 and PR c/88827 (r278976), this test emits
a different error message and needs an update.

2019-12-06  Christophe Lyon  <christophe.lyon@linaro.org>

	PR c/36941
	PR c/88827
	* gcc.target/aarch64/sve/acle/general-c/type_redef_11.c: Update
	expected diagnostics.



Modified:
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_11.c