From patchwork Wed Dec 4 23:26:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 1204402 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-515177-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="cO/hwcjr"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47Sw3z3mv2z9sNx for ; Thu, 5 Dec 2019 10:27:09 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=Qpqjcl04RsxQJYGm/6cuMylsfE9jcf8ew74eL9CLYVZjEDhIwC+qO qAi8tiVdsTEDqv8N/ckkd4rQA9CQ+c16eTRZb84yAcQobQCEPjdxun6yJ6gZNmbr wP9RevpXJPzCMs8iKE+n2H6F4cecd/qPtMx/OI7MiBfEYm2Zp7/7B4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=1HQ0DsC1ven61E61MHQKtX8v+KM=; b=cO/hwcjrtfw1yiKrjpqU pcooO97Bmcrn2tDgWH2/+W9KpFSyYz9YeFFwrat7pyM7aN3VGOCG6Nf2vpdfVyQ/ pQfn301ybb4w8vxDa/U4B+3I23svd2prjr4tbNgIFStw3N+3Lt5G/ty/fVuMjnvL aplFHY4cKBIseEdBQ2TENoc= Received: (qmail 91129 invoked by alias); 4 Dec 2019 23:27:00 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 91121 invoked by uid 89); 4 Dec 2019 23:27:00 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-7.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS autolearn=ham version=3.3.1 spammy=1314, 25526, yield, 20546 X-HELO: esa1.mentor.iphmx.com Received: from esa1.mentor.iphmx.com (HELO esa1.mentor.iphmx.com) (68.232.129.153) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 04 Dec 2019 23:26:57 +0000 IronPort-SDR: JC8HcQOkwV/hNoQfqW3CHQYk4MyqjaYSIFRP0kKp+5giwE4IiInrdJpllcZBurA2hqgCelpHoO HjRYlO2An8BG3RmXSfhodzXBtV65ubx1sDNW/yGl1L7v3oB+WjLgtLq5x63oD6Ml9dFjqaxJfu IvTvvjlN9vIKQ+jhrJfTZeQJ7ZS7S8//bBzJamIJeNQzA0NSPanpRb+JLJcyLY7UkWrRejcIvH TST/OzxtC66auddDSmVmo4y77viYyAjyTCU4JJBzr5oxGvptaeomxuVLbILbyIxFjl+1NOpy7q +yg= Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa1.mentor.iphmx.com with ESMTP; 04 Dec 2019 15:26:37 -0800 IronPort-SDR: sQd1/dK5U0daDsnRH4wjkHbW6KBpwosCbk0J5KD+3flLWJDc2KeRg4CJUknXautwiARC6GnaW3 3ex2A82KL4GNeTgAEmkr5JsAzqKoVdBQSIokq/Ul/e9qBkILcgTRhWEfoNswYRprte7JWmnmEG Lla8y0hRAa04+YJYoCeXMkvsG0Jk6C7XxxA/OxjJ0bGC6Z+i+9NSbLTcS5c9iAkNUNAJG81Hkb pun6kdhe3Zuh7BSUi+2j3DuL2A7kc0fPy4LtpCeuZcWGrodbVIM43GjH/UxbNKAyjAL4N8anQ7 f7c= Date: Wed, 4 Dec 2019 23:26:31 +0000 From: Joseph Myers To: Subject: Fix C handling of use of lvalues of incomplete types (PR c/36941, PR c/88827) Message-ID: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 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. Applied to mainline. gcc/c: 2019-12-04 Joseph Myers PR c/36941 PR c/88827 * 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: 2019-12-04 Joseph Myers PR c/36941 PR c/88827 * 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. Index: gcc/c/c-tree.h =================================================================== --- gcc/c/c-tree.h (revision 278975) +++ gcc/c/c-tree.h (working copy) @@ -55,9 +55,6 @@ along with GCC; see the file COPYING3. If not see This is used for -Wc++-compat. */ #define C_TYPE_DEFINED_IN_STRUCT(TYPE) TYPE_LANG_FLAG_2 (TYPE) -/* Record whether an "incomplete type" error was given for the type. */ -#define C_TYPE_ERROR_REPORTED(TYPE) TYPE_LANG_FLAG_3 (TYPE) - /* Record whether a typedef for type `int' was actually `signed int'. */ #define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP) Index: gcc/c/c-typeck.c =================================================================== --- gcc/c/c-typeck.c (revision 278975) +++ gcc/c/c-typeck.c (working copy) @@ -2054,6 +2054,8 @@ convert_lvalue_to_rvalue (location_t loc, struct c mark_exp_read (exp.value); if (convert_p) exp = default_function_array_conversion (loc, exp); + if (!VOID_TYPE_P (TREE_TYPE (exp.value))) + exp.value = require_complete_type (loc, exp.value); if (really_atomic_lvalue (exp.value)) { vec *params; @@ -2550,16 +2552,6 @@ build_indirect_ref (location_t loc, tree ptr, ref_ ref = build1 (INDIRECT_REF, t, pointer); - if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) - { - if (!C_TYPE_ERROR_REPORTED (TREE_TYPE (ptr))) - { - error_at (loc, "dereferencing pointer to incomplete type " - "%qT", t); - C_TYPE_ERROR_REPORTED (TREE_TYPE (ptr)) = 1; - } - return error_mark_node; - } if (VOID_TYPE_P (t) && c_inhibit_evaluation_warnings == 0) warning_at (loc, 0, "dereferencing % pointer"); Index: gcc/testsuite/gcc.dg/array-8.c =================================================================== --- gcc/testsuite/gcc.dg/array-8.c (revision 278975) +++ gcc/testsuite/gcc.dg/array-8.c (working copy) @@ -43,6 +43,5 @@ g (void) pv[0]; /* { dg-warning "dereferencing 'void \\*' pointer" } */ 0[pv]; /* { dg-warning "dereferencing 'void \\*' pointer" } */ sip[0]; /* { dg-error "invalid use of undefined type 'struct si'" } */ - /* { dg-error "dereferencing pointer to incomplete type" "incomplete" { target *-*-* } .-1 } */ 0[sip]; /* { dg-error "invalid use of undefined type 'struct si'" } */ } Index: gcc/testsuite/gcc.dg/enum-incomplete-1.c =================================================================== --- gcc/testsuite/gcc.dg/enum-incomplete-1.c (revision 278975) +++ gcc/testsuite/gcc.dg/enum-incomplete-1.c (working copy) @@ -13,14 +13,16 @@ f0 (int i) { ve; /* { dg-error "incomplete" } */ vs; /* { dg-error "incomplete" } */ - (void) ve; - (void) vs; + (void) ve; /* { dg-error "incomplete" } */ + (void) vs; /* { dg-error "incomplete" } */ (void) (i ? ve : ve); /* { dg-error "incomplete" } */ (void) (i ? vs : vs); /* { dg-error "incomplete" } */ (void) (ve = ve); /* { dg-error "incomplete" } */ (void) (vs = vs); /* { dg-error "incomplete" } */ - (void) ve, (void) ve; - (void) vs, (void) vs; + (void) ve, /* { dg-error "incomplete" } */ + (void) ve; /* { dg-error "incomplete" } */ + (void) vs, /* { dg-error "incomplete" } */ + (void) vs; /* { dg-error "incomplete" } */ p = &ve; p = &vs; (void) sizeof (ve); /* { dg-error "incomplete" } */ Index: gcc/testsuite/gcc.dg/enum-incomplete-3.c =================================================================== --- gcc/testsuite/gcc.dg/enum-incomplete-3.c (revision 278975) +++ gcc/testsuite/gcc.dg/enum-incomplete-3.c (working copy) @@ -4,17 +4,17 @@ enum E e; /* { dg-error "storage size" } */ -void bar (int [e]); /* { dg-error "size of unnamed array has incomplete type" } */ -void bar2 (int [][e]); /* { dg-error "size of unnamed array has incomplete type" } */ +void bar (int [e]); /* { dg-error "has an incomplete type" } */ +void bar2 (int [][e]); /* { dg-error "has an incomplete type" } */ void foo (void) { - int a1[e]; /* { dg-error "size of array .a1. has incomplete type" } */ - int a2[e][3]; /* { dg-error "size of array .a2. has incomplete type" } */ + int a1[e]; /* { dg-error "has an incomplete type" } */ + int a2[e][3]; /* { dg-error "has an incomplete type" } */ struct S { - int a3[e]; /* { dg-error "size of array .a3. has incomplete type" } */ + int a3[e]; /* { dg-error "has an incomplete type" } */ }; } Index: gcc/testsuite/gcc.dg/lvalue-10.c =================================================================== --- gcc/testsuite/gcc.dg/lvalue-10.c (nonexistent) +++ gcc/testsuite/gcc.dg/lvalue-10.c (working copy) @@ -0,0 +1,22 @@ +/* Test handling of lvalues of incomplete types. Bugs 36941, 88647 + (invalid), 88827. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +struct S; + +extern struct S var; +extern struct S *vp; + +void +f8 (void) +{ + /* These are valid because there is no constraint violation and the + result of '*' is never converted from an lvalue to an rvalue + (which would yield undefined behavior). */ + &var; + &*vp; + &(var); + &(*vp); + &*&*vp; +} Index: gcc/testsuite/gcc.dg/lvalue-9.c =================================================================== --- gcc/testsuite/gcc.dg/lvalue-9.c (nonexistent) +++ gcc/testsuite/gcc.dg/lvalue-9.c (working copy) @@ -0,0 +1,77 @@ +/* Test handling of lvalues of incomplete types. Bugs 36941, 88647 + (invalid), 88827. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +struct S; + +extern struct S var; +extern struct S *vp; +extern int i; + +void +f1 (void) +{ + var; /* { dg-error "has an incomplete type" } */ + var, (void) 0; /* { dg-error "has an incomplete type" } */ + (i + ? var /* { dg-error "has an incomplete type" } */ + : var); /* { dg-error "has an incomplete type" } */ +} + +void +f2 (void) +{ + (void) var; /* { dg-error "has an incomplete type" } */ + (void) (var, (void) 0); /* { dg-error "has an incomplete type" } */ + (void) (i + ? var /* { dg-error "has an incomplete type" } */ + : var); /* { dg-error "has an incomplete type" } */ +} + +void +f3 (void) +{ + (const void) var; /* { dg-error "has an incomplete type" } */ + (const void) (var, (void) 0); /* { dg-error "has an incomplete type" } */ + (const void) (i + ? var /* { dg-error "has an incomplete type" } */ + : var); /* { dg-error "has an incomplete type" } */ +} + +void +f4 (void) +{ + *vp; /* { dg-error "invalid use of undefined type" } */ + *vp, (void) 0; /* { dg-error "invalid use of undefined type" } */ + (i + ? *vp /* { dg-error "invalid use of undefined type" } */ + : *vp); /* { dg-error "invalid use of undefined type" } */ +} + +void +f5 (void) +{ + (void) *vp; /* { dg-error "invalid use of undefined type" } */ + (void) (*vp, (void) 0); /* { dg-error "invalid use of undefined type" } */ + (void) (i + ? *vp /* { dg-error "invalid use of undefined type" } */ + : *vp); /* { dg-error "invalid use of undefined type" } */ +} + +void +f6 (void) +{ + (const void) *vp; /* { dg-error "invalid use of undefined type" } */ + (const void) (*vp, (void) 0); /* { dg-error "invalid use of undefined type" } */ + (const void) (i + ? *vp /* { dg-error "invalid use of undefined type" } */ + : *vp); /* { dg-error "invalid use of undefined type" } */ +} + +void +f7 (void) +{ + /* This is invalid because of the constraints on []. */ + &vp[0]; /* { dg-error "invalid use of undefined type" } */ +} Index: gcc/testsuite/gcc.dg/noncompile/incomplete-3.c =================================================================== --- gcc/testsuite/gcc.dg/noncompile/incomplete-3.c (revision 278975) +++ gcc/testsuite/gcc.dg/noncompile/incomplete-3.c (working copy) @@ -5,5 +5,5 @@ int foo (void) { b_t d; struct b_t *c = &d; /* { dg-warning "incompatible pointer type" } */ - c->a; /* { dg-error "incomplete type" } */ + c->a; /* { dg-error "invalid use of undefined type" } */ } Index: gcc/testsuite/gcc.dg/pr48552-1.c =================================================================== --- gcc/testsuite/gcc.dg/pr48552-1.c (revision 278975) +++ gcc/testsuite/gcc.dg/pr48552-1.c (working copy) @@ -43,11 +43,12 @@ f6 (void *x) void f7 (struct S *x) { - __asm volatile ("" : : "r" (*x)); /* { dg-error "dereferencing pointer to incomplete type" } */ + __asm volatile ("" : : "r" (*x)); /* { dg-error "invalid use of undefined type" } */ } void f8 (struct S *x) { - __asm volatile ("" : "=r" (*x)); /* { dg-error "invalid lvalue in 'asm' output 0" } */ + __asm volatile ("" : "=r" (*x)); /* { dg-error "impossible constraint in 'asm'" } */ + /* { dg-error "non-memory output 0 must stay in memory" "memory" { target *-*-* } .-1 } */ } Index: gcc/testsuite/gcc.dg/pr48552-2.c =================================================================== --- gcc/testsuite/gcc.dg/pr48552-2.c (revision 278975) +++ gcc/testsuite/gcc.dg/pr48552-2.c (working copy) @@ -43,11 +43,12 @@ f6 (void *x) void f7 (struct S *x) { - __asm ("" : : "r" (*x)); /* { dg-error "dereferencing pointer to incomplete type" } */ + __asm ("" : : "r" (*x)); /* { dg-error "invalid use of undefined type" } */ } void f8 (struct S *x) { - __asm ("" : "=r" (*x)); /* { dg-error "invalid lvalue in 'asm' output 0" } */ + __asm ("" : "=r" (*x)); /* { dg-error "impossible constraint in 'asm'" } */ + /* { dg-error "non-memory output 0 must stay in memory" "memory" { target *-*-* } .-1 } */ } Index: gcc/testsuite/gcc.dg/pr63543.c =================================================================== --- gcc/testsuite/gcc.dg/pr63543.c (revision 278975) +++ gcc/testsuite/gcc.dg/pr63543.c (working copy) @@ -7,15 +7,15 @@ union U; int f1 (struct S *s) { - return s->a /* { dg-error "dereferencing pointer to incomplete type .struct S." } */ - + s->b - + s->c; + return s->a /* { dg-error "invalid use of undefined type .struct S." } */ + + s->b /* { dg-error "invalid use of undefined type .struct S." } */ + + s->c; /* { dg-error "invalid use of undefined type .struct S." } */ } int f2 (union U *u) { - return u->a /* { dg-error "dereferencing pointer to incomplete type .union U." } */ - + u->a - + u->a; + return u->a /* { dg-error "invalid use of undefined type .union U." } */ + + u->a /* { dg-error "invalid use of undefined type .union U." } */ + + u->a; /* { dg-error "invalid use of undefined type .union U." } */ } Index: gcc/testsuite/gcc.dg/pr69796.c =================================================================== --- gcc/testsuite/gcc.dg/pr69796.c (revision 278975) +++ gcc/testsuite/gcc.dg/pr69796.c (working copy) @@ -6,5 +6,5 @@ struct S s; /* { dg-error "storage size of 's' isn void foo () { - s a; /* { dg-error "expression statement has incomplete type|expected" } */ + s a; /* { dg-error "has an incomplete type|expected" } */ }