From patchwork Sat Sep 7 21:17:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Frost X-Patchwork-Id: 1982171 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4X1Qtr2LXZz1y1D for ; Sun, 8 Sep 2024 07:18:26 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6046C385DDC4 for ; Sat, 7 Sep 2024 21:18:24 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx2.mythic-beasts.com (mx2.mythic-beasts.com [IPv6:2a00:1098:0:82:1000:0:2:1]) by sourceware.org (Postfix) with ESMTPS id 0BE613858C33 for ; Sat, 7 Sep 2024 21:17:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0BE613858C33 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=pfrost.me Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=pfrost.me ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0BE613858C33 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1098:0:82:1000:0:2:1 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725743881; cv=none; b=SRIdknb7YZZr7FEKfRb9/oP7/+OLkTog78WhxID1HFEYaRgpPX8cjSIN0gdXGK5tHlDFliYqcl9ERJbShRtKpsACHZ75WEeutsgYA4y1k/Qi3ECuw6A3rso2Xv+fGjpQT0MLGjQLxRDdh8LSa56FwSPKJcih8i4KB8Slz/iCCKE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725743881; c=relaxed/simple; bh=W9XVlf8WF1driJPXi7HP5e2sVXF9HC4DVYvRN7VaQUY=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=e4l2dXOUdWY1yJdxK3dhDZfLiOXeirXGv2ATGI4UO9hFdK6lZEsynu23w3rlmq/+M9ypI142jwM674ZfdL5+lfoRqyz3IWKAyZY9VIqnINNxNLZksvaVvuMSzxG+Kqmp1yRZh3nfUIBo5fz+OY4pd51qBkTEgCcuNmA+Y6KEoVM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mailhub-hex-d.mythic-beasts.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sn2of-00HDXh-JE; Sat, 07 Sep 2024 22:17:57 +0100 From: Peter Frost To: gcc-patches@gcc.gnu.org Cc: pinskia@gmail.com, Peter Frost Subject: [PATCH v2] Add new warning Wmissing-designated-initializers [PR39589] Date: Sat, 7 Sep 2024 22:17:14 +0100 Message-Id: <20240907211714.8665-1-mail@pfrost.me> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 X-BlackCat-Spam-Score: 49 X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_INFOUSMEBIZ, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org v2 Patch: * adds proper changelog text * fixes typo in c.opt Currently the behaviour of Wmissing-field-initializers is inconsistent between C and C++. The C warning assumes that missing designated initializers are deliberate, and does not warn. The C++ warning does warn for missing designated initializers. This patch changes the behaviour of Wmissing-field-initializers to universally not warn about missing designated initializers, and adds a new warning for specifically for missing designated initializers. NOTE TO MAINTAINERS: This is my first gcc contribution, so I don't have git write access. Successfully tested on x86_64-pc-linux-gnu. PR c/39589 gcc/c-family/ChangeLog: * c.opt: Added new option Wmissing-designated-initializers, enabled by Wextra gcc/c/ChangeLog: * c-typeck.cc (pop_init_level): Generate warning for missing designated initializers rather than always ignore gcc/cp/ChangeLog: * typeck2.cc (process_init_constructor_record): Add check if missing initializer is designated, warn as appropriate gcc/testsuite/ChangeLog: * g++.dg/diagnostic/base.C: Change flags * gcc.dg/20011021-1.c: Fix test, missing designated initializers can generate a warning now * gcc.dg/missing-field-init-1.c: Change flags * gcc.dg/pr60784.c: Change flags * g++.dg/warn/missing-designated-initializers-1.C: New test. * g++.dg/warn/missing-designated-initializers-2.C: New test. * gcc.dg/missing-designated-initializers-1.c: New test. * gcc.dg/missing-designated-initializers-2.c: New test. --- gcc/c-family/c.opt | 4 +++ gcc/c/c-typeck.cc | 36 +++++++++++-------- gcc/cp/typeck2.cc | 20 ++++++++--- gcc/testsuite/g++.dg/diagnostic/base.C | 4 +-- .../warn/missing-designated-initializers-1.C | 11 ++++++ .../warn/missing-designated-initializers-2.C | 11 ++++++ gcc/testsuite/gcc.dg/20011021-1.c | 4 +-- .../missing-designated-initializers-1.c | 13 +++++++ .../missing-designated-initializers-2.c | 13 +++++++ gcc/testsuite/gcc.dg/missing-field-init-1.c | 2 +- gcc/testsuite/gcc.dg/pr60784.c | 2 +- 11 files changed, 96 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/missing-designated-initializers-1.C create mode 100644 gcc/testsuite/g++.dg/warn/missing-designated-initializers-2.C create mode 100644 gcc/testsuite/gcc.dg/missing-designated-initializers-1.c create mode 100644 gcc/testsuite/gcc.dg/missing-designated-initializers-2.c diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 491aa02e1a3..81e52f1417e 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -977,6 +977,10 @@ Wmissing-field-initializers C ObjC C++ ObjC++ Var(warn_missing_field_initializers) Warning EnabledBy(Wextra) Warn about missing fields in struct initializers. +Wmissing-designated-initializers +C ObjC C++ ObjC++ Var(warn_missing_designated_initializers) Warning EnabledBy(Wextra) +Warn about missing designated initializers in struct initializers. + Wmissing-format-attribute C ObjC C++ ObjC++ Warning Alias(Wsuggest-attribute=format) ; diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 094e41fa202..72b544e8f67 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -9795,7 +9795,7 @@ pop_init_level (location_t loc, int implicit, } /* Warn when some struct elements are implicitly initialized to zero. */ - if (warn_missing_field_initializers + if ((warn_missing_field_initializers || warn_missing_designated_initializers) && constructor_type && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_unfilled_fields) @@ -9806,21 +9806,29 @@ pop_init_level (location_t loc, int implicit, || integer_zerop (DECL_SIZE (constructor_unfilled_fields)))) constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields); - if (constructor_unfilled_fields - /* Do not warn if this level of the initializer uses member - designators; it is likely to be deliberate. */ - && !constructor_designated - /* Do not warn about initializing with { 0 } or with { }. */ - && !constructor_zeroinit) - { - if (warning_at (input_location, OPT_Wmissing_field_initializers, + if (constructor_unfilled_fields + /* Do not warn about initializing with { 0 } or with { }. */ + && !constructor_zeroinit) + { + if (!constructor_designated) + { + if (warning_at (input_location, OPT_Wmissing_field_initializers, "missing initializer for field %qD of %qT", - constructor_unfilled_fields, - constructor_type)) - inform (DECL_SOURCE_LOCATION (constructor_unfilled_fields), + constructor_unfilled_fields, constructor_type)) + inform (DECL_SOURCE_LOCATION (constructor_unfilled_fields), + "%qD declared here", constructor_unfilled_fields); + } + else if (warn_missing_designated_initializers) + { + if (warning_at ( + input_location, OPT_Wmissing_designated_initializers, + "missing designated initializer for field %qD of %qT", + constructor_unfilled_fields, constructor_type)) + inform (DECL_SOURCE_LOCATION (constructor_unfilled_fields), "%qD declared here", constructor_unfilled_fields); - } - } + } + } + } /* Pad out the end of the structure. */ if (p->replacement_value.value) diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc index 30a6fbe95c9..6d21caf53d7 100644 --- a/gcc/cp/typeck2.cc +++ b/gcc/cp/typeck2.cc @@ -1822,8 +1822,14 @@ process_init_constructor_record (tree type, tree init, int nested, int flags, if ((complain & tf_warning) && !cp_unevaluated_operand && !EMPTY_CONSTRUCTOR_P (init)) - warning (OPT_Wmissing_field_initializers, - "missing initializer for member %qD", field); + { + if (CONSTRUCTOR_IS_DESIGNATED_INIT (init)) + warning (OPT_Wmissing_designated_initializers, + "missing designated initializer for member %qD", field); + else + warning (OPT_Wmissing_field_initializers, + "missing initializer for member %qD", field); + } } else { @@ -1853,8 +1859,14 @@ process_init_constructor_record (tree type, tree init, int nested, int flags, && !cp_unevaluated_operand && !EMPTY_CONSTRUCTOR_P (init) && !is_really_empty_class (fldtype, /*ignore_vptr*/false)) - warning (OPT_Wmissing_field_initializers, - "missing initializer for member %qD", field); + { + if (CONSTRUCTOR_IS_DESIGNATED_INIT (init)) + warning (OPT_Wmissing_designated_initializers, + "missing designated initializer for member %qD", field); + else + warning (OPT_Wmissing_field_initializers, + "missing initializer for member %qD", field); + } if (!zero_init_p (fldtype) || skipped < 0) { diff --git a/gcc/testsuite/g++.dg/diagnostic/base.C b/gcc/testsuite/g++.dg/diagnostic/base.C index 1540414072e..d8c644f78f5 100644 --- a/gcc/testsuite/g++.dg/diagnostic/base.C +++ b/gcc/testsuite/g++.dg/diagnostic/base.C @@ -1,6 +1,6 @@ // PR c++/110745 // { dg-do compile { target c++17 } } -// { dg-options "-Wmissing-field-initializers" } +// { dg-options "-Wmissing-designated-initializers" } struct B { int i; }; struct D : B { @@ -11,6 +11,6 @@ struct D : B { int main () { - D d = {.x=1, .y=2}; // { dg-warning "missing initializer for member .D::B." } + D d = {.x=1, .y=2}; // { dg-warning "missing designated initializer for member .D::B." } (void)d; } diff --git a/gcc/testsuite/g++.dg/warn/missing-designated-initializers-1.C b/gcc/testsuite/g++.dg/warn/missing-designated-initializers-1.C new file mode 100644 index 00000000000..86afafc5e9b --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/missing-designated-initializers-1.C @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-Wextra -Wmissing-designated-initializers" } */ + +struct s { int a, b, c; }; +struct s s1 = { .a = 1, .b = 2, .c = 3 }; +struct s s2 = { .a = 1, .b = 2 }; /* { dg-warning "missing designated initializer" } */ +struct s s3 = { .a = 1 }; /* { dg-warning "missing designated initializer" } */ + +struct s s6[] = { { .a = 1, .b = 2, .c = 3 }, { .a = 4 } }; /* { dg-warning "missing designated initializer" } */ +struct s s7[] = { { .a = 1 }, { .a = 2, .b = 3, .c = 4 } }; /* { dg-warning "missing designated initializer" } */ +struct s s8[] = { { 1, 2, 3 }, { .a = 4 } }; /* { dg-warning "missing designated initializer" } */ diff --git a/gcc/testsuite/g++.dg/warn/missing-designated-initializers-2.C b/gcc/testsuite/g++.dg/warn/missing-designated-initializers-2.C new file mode 100644 index 00000000000..b47af7baac5 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/missing-designated-initializers-2.C @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-Wextra -Wno-missing-designated-initializers" } */ + +struct s { int a, b, c; }; +struct s s1 = { .a = 1, .b = 2, .c = 3 }; +struct s s2 = { .a = 1, .b = 2 }; /* { dg-bogus "missing designated initializer" } */ +struct s s3 = { .a = 1 }; /* { dg-bogus "missing designated initializer" } */ + +struct s s6[] = { { .a = 1, .b = 2, .c = 3 }, { .a = 4 } }; /* { dg-bogus "missing designated initializer" } */ +struct s s7[] = { { .a = 1 }, { .a = 2, .b = 3, .c = 4 } }; /* { dg-bogus "missing designated initializer" } */ +struct s s8[] = { { 1, 2, 3 }, { .a = 4 } }; /* { dg-bogus "missing designated initializer" } */ diff --git a/gcc/testsuite/gcc.dg/20011021-1.c b/gcc/testsuite/gcc.dg/20011021-1.c index 2d567a75381..66964541d05 100644 --- a/gcc/testsuite/gcc.dg/20011021-1.c +++ b/gcc/testsuite/gcc.dg/20011021-1.c @@ -29,7 +29,7 @@ struct multilevel struct t T0 = { 1 }; /* { dg-warning "missing init" } */ -struct t T1 = { .a = 1 }; /* { dg-bogus "(missing|near) init" } */ +struct t T1 = { .a = 1 }; /* { dg-warning "missing designated initializer" } */ union u U0 = { 1 }; /* { dg-warning "initialization of union" } */ union u U1 = { .i = 1 }; /* { dg-bogus "initialization of union" } */ @@ -37,7 +37,7 @@ union u U1 = { .i = 1 }; /* { dg-bogus "initialization of union" } */ struct multilevel M = { 12, - { .b = 3 }, /* { dg-bogus "missing init" } */ + { .b = 3 }, /* { dg-warning "missing designated initializer" } */ { 4 }, /* { dg-warning "initialization of union" } */ { .n = 9 }, /* { dg-bogus "initialization of union" } */ /* "string here" */ diff --git a/gcc/testsuite/gcc.dg/missing-designated-initializers-1.c b/gcc/testsuite/gcc.dg/missing-designated-initializers-1.c new file mode 100644 index 00000000000..817386785f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/missing-designated-initializers-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-Wextra -Wmissing-designated-initializers" } */ + +struct s { int a, b, c; }; +struct s s1 = { .a = 1, .b = 2, .c = 3 }; +struct s s2 = { .a = 1, .b = 2 }; /* { dg-warning "missing designated initializer" } */ +struct s s3 = { .a = 1 }; /* { dg-warning "missing designated initializer" } */ +struct s s4 = { .a = 1, 2 }; /* { dg-warning "missing designated initializer" } */ +struct s s5 = { .a = 1, 2, 3 }; /* { dg-bogus "missing designated initializer" } */ + +struct s s6[] = { { .a = 1, .b = 2, .c = 3 }, { .a = 4 } }; /* { dg-warning "missing designated initializer" } */ +struct s s7[] = { { .a = 1 }, { .a = 2, .b = 3, .c = 4 } }; /* { dg-warning "missing designated initializer" } */ +struct s s8[] = { { 1, 2, 3 }, { .a = 4 } }; /* { dg-warning "missing designated initializer" } */ diff --git a/gcc/testsuite/gcc.dg/missing-designated-initializers-2.c b/gcc/testsuite/gcc.dg/missing-designated-initializers-2.c new file mode 100644 index 00000000000..dc2c6bb51f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/missing-designated-initializers-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-Wextra -Wno-missing-designated-initializers" } */ + +struct s { int a, b, c; }; +struct s s1 = { .a = 1, .b = 2, .c = 3 }; +struct s s2 = { .a = 1, .b = 2 }; /* { dg-bogus "missing designated initializer" } */ +struct s s3 = { .a = 1 }; /* { dg-bogus "missing designated initializer" } */ +struct s s4 = { .a = 1, 2 }; /* { dg-bogus "missing designated initializer" } */ +struct s s5 = { .a = 1, 2, 3 }; /* { dg-bogus "missing designated initializer" } */ + +struct s s6[] = { { .a = 1, .b = 2, .c = 3 }, { .a = 4 } }; /* { dg-bogus "missing designated initializer" } */ +struct s s7[] = { { .a = 1 }, { .a = 2, .b = 3, .c = 4 } }; /* { dg-bogus "missing designated initializer" } */ +struct s s8[] = { { 1, 2, 3 }, { .a = 4 } }; /* { dg-bogus "missing designated initializer" } */ diff --git a/gcc/testsuite/gcc.dg/missing-field-init-1.c b/gcc/testsuite/gcc.dg/missing-field-init-1.c index 5f32b021f0a..cd43fcc4f06 100644 --- a/gcc/testsuite/gcc.dg/missing-field-init-1.c +++ b/gcc/testsuite/gcc.dg/missing-field-init-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Wextra -Wno-missing-field-initializers -std=c99" } */ +/* { dg-options "-Wextra -Wno-missing-field-initializers -Wno-missing-designated-initializers -std=c99" } */ struct s { int a, b, c; }; struct s s1 = { 1, 2, 3 }; diff --git a/gcc/testsuite/gcc.dg/pr60784.c b/gcc/testsuite/gcc.dg/pr60784.c index 82b512f7c2e..60532831f4f 100644 --- a/gcc/testsuite/gcc.dg/pr60784.c +++ b/gcc/testsuite/gcc.dg/pr60784.c @@ -1,6 +1,6 @@ /* PR c/60784 */ /* { dg-do compile } */ -/* { dg-options "-Wextra -std=c99" } */ +/* { dg-options "-Wextra -Wno-missing-designated-initializers -std=c99" } */ struct A { int i, j; }; struct B { struct A a; } b1 = { .a.i = 1, .a.j = 1 };