From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by sourceware.org (Postfix) with ESMTPS id 134803858036 for ; Thu, 4 Nov 2021 23:37:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 134803858036 Received: by mail-lf1-x133.google.com with SMTP id bq11so15144410lfb.10 for ; Thu, 04 Nov 2021 16:37:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=82hJF3RgkiGujknmvLpA6pqpkZ7riislUQl28R6X1xE=; b=ef3APtpnEsL7muJcCaNrjaIUW/MWaiynM0QsdAQbiz7Wbo9fYqkd/QIwllEHiyHrmT TjteIO4h+N1SPJDIsnDtRQLcmT1FJlUn1UIIKcLaEj2GBETbT4Q1MOdtE8osa5BsIZKV agsmZztutAN5ylRtXT9dGdjE3l+JdkTfMAhfHK0+TQ+/lE2Zoe1H3aA7EHmn8glbzb3Y uOHBmcHGoQTIA0Rj6ZSQUyoKp5zntiUORo/X8Wl6WjebDUhBmxC2+ESWkREWZc6ovYt7 fUQNyvdOgtYri78/3qTakTFs3sS0xcWzm7EmqYW/AdHW3BMOR812ZOrYjXtv+8etZTH+ x9rA== X-Gm-Message-State: AOAM531LxkhqmeYghvCCjraEG3Dfh0FR3QHw+2ZVcnGDtYmKGeF6PDHu J7A75Imqf8oNpZ3O8EylwAYJCZ+MQmT8OKleGo+b8MPdSy8= X-Google-Smtp-Source: ABdhPJzHH/x2D0sxGCnZS3upnlkevY1VArVqvGqZTTK6emlKB5RpbaR6yysO3qHHIQvhBhWQaf3GWRnHzMXPbBqrQSc= X-Received: by 2002:a05:6512:308e:: with SMTP id z14mr14897872lfd.294.1636069058280; Thu, 04 Nov 2021 16:37:38 -0700 (PDT) MIME-Version: 1.0 From: will wray Date: Thu, 4 Nov 2021 19:37:27 -0400 Message-ID: Subject: [PATCH] c++ PR 55227: designated init of char array by string constant To: gcc-patches List Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-6.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 04 Nov 2021 23:37:42 -0000 This patch aims to fix PR 55227; two underlying bugs that have caused: (1) Rejection of valid designated initialization of char array fields by string literals (a) when enclosed in optional braces or (b) unbraced when the string literal is shorter than the target char array field. (2) Acceptance of an invalid designator appearing within the braces of a braced string literal, in which case the 'designator' was entirely ignored and the string literal treated as a positional initializer. Please review these changes carefully; I'm fairly new to this, so likely to have made errors of omission, logic or an anon anomaly. The fixes above also allow to address a FIXME in cp_complete_array_type, otherwise obstructed by the designator bugs (see relevant comment here https://patchwork.ozlabs.org/project/gcc/list/?series=199783) Please suggest test cases for the newly inserted call to reshape_init. (This patch is split from my upcoming 'P1997 array copy-semantic' patch, which will then extend this from string literal to any array value.) Boostraps/regtests on x86_64-pc-linux-gnu. PR c++/55227 gcc/cp/ChangeLog: * decl.c (reshape_init_r): restrict has_designator_check, (cp_complete_array_type): do reshape_init on braced-init-list. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/desig20.C: New test. --- diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7c2a134e406..3bd6ed68a45 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6820,6 +6820,7 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, { tree str_init = init; tree stripped_str_init = stripped_init; + reshape_iter stripd = {}; /* Strip one level of braces if and only if they enclose a single element (as allowed by [dcl.init.string]). */ @@ -6827,7 +6828,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, && TREE_CODE (stripped_str_init) == CONSTRUCTOR && CONSTRUCTOR_NELTS (stripped_str_init) == 1) { - str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value; + stripd.cur = CONSTRUCTOR_ELT (stripped_str_init, 0); + str_init = stripd.cur->value; stripped_str_init = tree_strip_any_location_wrapper (str_init); } @@ -6836,7 +6838,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, array types (one value per array element). */ if (TREE_CODE (stripped_str_init) == STRING_CST) { - if (has_designator_problem (d, complain)) + if ((first_initializer_p && has_designator_problem (d, complain)) + || (stripd.cur && has_designator_problem (&stripd, complain))) return error_mark_node; d->cur++; return str_init; @@ -9541,23 +9544,10 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default) unsigned HOST_WIDE_INT i; tree value; - /* An array of character type can be initialized from a - brace-enclosed string constant. - - FIXME: this code is duplicated from reshape_init. Probably - we should just call reshape_init here? */ - if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype))) - && TREE_CODE (initial_value) == CONSTRUCTOR - && !vec_safe_is_empty (CONSTRUCTOR_ELTS (initial_value))) - { - vec *v = CONSTRUCTOR_ELTS (initial_value); - tree value = (*v)[0].value; - STRIP_ANY_LOCATION_WRAPPER (value); - - if (TREE_CODE (value) == STRING_CST - && v->length () == 1) - initial_value = value; - } + if (TREE_CODE (initial_value) == CONSTRUCTOR + && BRACE_ENCLOSED_INITIALIZER_P (initial_value)) + initial_value = reshape_init (*ptype, initial_value, + tf_warning_or_error); /* If any of the elements are parameter packs, we can't actually complete this type now because the array size is dependent. */ diff --git a/gcc/testsuite/g++.dg/cpp2a/desig20.C b/gcc/testsuite/g++.dg/cpp2a/desig20.C new file mode 100644 index 00000000000..eb3ef5eda08 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/desig20.C @@ -0,0 +1,47 @@ +// PR c++/55227 +// Test designated initializer for char array by string constant + +// { dg-do compile } +// { dg-options "-pedantic" } + +struct C {char a[2];}; + +/* Case a, designated, unbraced, string-literal of the exact same size + as the initialized char array; valid and accepted before and after. +*/ +C a = {.a="a"}; // { dg-warning "designated initializers only available with" "" { target c++17_down } .-0 } + +/* Cases b,c,d, designated, braced or mimatched-size, string literal, + previously rejected; "C99 designator 'a' outside aggregate initializer". +*/ +C b = {.a=""}; // { dg-warning "designated initializers only available with" "" { target c++17_down } .-0 } +C c = {.a={""}}; // { dg-warning "designated initializers only available with" "" { target c++17_down } .-0 } +C d = {.a={"a"}}; // { dg-warning "designated initializers only available with" "" { target c++17_down } .-0 } + +/* Case e, designated char array field and braced, designated array element(s) + (with GNU [N]= extension) valid and accepted before and after. +*/ +C e = {.a={[0]='a'}}; // { dg-warning "ISO C.. does not allow C99 designated initializers" } +// { dg-warning "designated initializers only available with" "" { target c++17_down } .-1 } + +/* Cases f,g,h, braced string literal, 'designated' within inner braces; + invalid, previously accepted as positional with 'designator' ignored. +*/ +C f = {{[0]="a"}}; // { dg-error "C99 designator .0. outside aggregate initializer" } +// { dg-warning "ISO C.. does not allow C99 designated initializers" "C99 desig" { target *-*-* } .-1 } +C g = {{.a="a"}}; // { dg-error "C99 designator .a. outside aggregate initializer" } +// { dg-warning "designated initializers only available with" "" { target c++17_down } .-1 } +C h = {{.b="a"}}; // { dg-error "C99 designator .b. outside aggregate initializer" } +// { dg-warning "designated initializers only available with" "" { target c++17_down } .-1 } + +template +void t() +{ + C ca[] = { {.a=""}, {.a={""}}, }; +// { dg-warning "designated initializers only available with" "" { target c++17_down } .-1 } +} + +void u() +{ + return t(); +}