From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by sourceware.org (Postfix) with ESMTPS id A35633858412 for ; Wed, 1 Feb 2023 11:41:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A35633858412 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out1.suse.de (Postfix) with ESMTP id D826533C26; Wed, 1 Feb 2023 11:41:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1675251688; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=TXEFo5c8FYPVHiJcQ1XnEhn+QE0Y4OisxS46gOpV/0c=; b=fflGvQ8shTWMq/RQN04my7+aW+wE+S2Ze2i77bMMWG1ZFe57VPcvexnRPp/5HyF+zlCUGc Z0MIkqqi9UV0l8Te37NY01pBweBASroXh9n1sg4tyXiPJEnf2RC7JN4hZo6vh0bd9/M3LZ Gppn7iUMfpuaPzUEdsxpPBUgHieJxbI= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1675251688; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=TXEFo5c8FYPVHiJcQ1XnEhn+QE0Y4OisxS46gOpV/0c=; b=96uMp0Rj1Ei9v6IjKJMqfDD5PElFmfqI/eTxqMHCHcrS8f18BamEW/EjyQvSya1Mx2jbvW 6NNHz1jz63JiAsAQ== Received: from wotan.suse.de (wotan.suse.de [10.160.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by relay2.suse.de (Postfix) with ESMTPS id 8CC6F2C141; Wed, 1 Feb 2023 11:41:28 +0000 (UTC) Date: Wed, 1 Feb 2023 11:41:28 +0000 (UTC) From: Richard Biener To: Qing Zhao cc: gcc-patches@gcc.gnu.org, siddhesh@gotplt.org, keescook@chromium.org Subject: Re: [PATCH 1/2] Handle component_ref to a structre/union field including flexible array member [PR101832] In-Reply-To: <20230131141140.3610133-2-qing.zhao@oracle.com> Message-ID: References: <20230131141140.3610133-1-qing.zhao@oracle.com> <20230131141140.3610133-2-qing.zhao@oracle.com> User-Agent: Alpine 2.22 (LSU 394 2020-01-19) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,SPF_HELO_NONE,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 List-Id: On Tue, 31 Jan 2023, Qing Zhao wrote: > GCC extension accepts the case when a struct with a flexible array member > is embedded into another struct (possibly recursively). > __builtin_object_size should treat such struct as flexible size per > -fstrict-flex-arrays. > > PR tree-optimization/101832 > > gcc/ChangeLog: > > PR tree-optimization/101832 > * tree-object-size.cc (flexible_size_type_p): New function. > (addr_object_size): Handle structure/union type when it has > flexible size. > > gcc/testsuite/ChangeLog: > > PR tree-optimization/101832 > * gcc.dg/builtin-object-size-pr101832-2.c: New test. > * gcc.dg/builtin-object-size-pr101832-3.c: New test. > * gcc.dg/builtin-object-size-pr101832-4.c: New test. > * gcc.dg/builtin-object-size-pr101832.c: New test. > --- > .../gcc.dg/builtin-object-size-pr101832-2.c | 135 ++++++++++++++++++ > .../gcc.dg/builtin-object-size-pr101832-3.c | 135 ++++++++++++++++++ > .../gcc.dg/builtin-object-size-pr101832-4.c | 135 ++++++++++++++++++ > .../gcc.dg/builtin-object-size-pr101832.c | 119 +++++++++++++++ > gcc/tree-object-size.cc | 115 +++++++++++---- > 5 files changed, 611 insertions(+), 28 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c > create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c > create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c > create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c > > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c > new file mode 100644 > index 00000000000..f38babc5415 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c > @@ -0,0 +1,135 @@ > +/* PR 101832: > + GCC extension accepts the case when a struct with a flexible array member > + is embedded into another struct (possibly recursively). > + __builtin_object_size will treat such struct as flexible size per > + -fstrict-flex-arrays. */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -fstrict-flex-arrays=1" } */ > + > +#include > + > +unsigned n_fails = 0; > + > +#define expect(p, _v) do { \ > + size_t v = _v; \ > + if (p == v) \ > + printf("ok: %s == %zd\n", #p, p); \ > + else {\ > + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ > + n_fails++; \ > + } \ > +} while (0); > + > +struct A { > + int n; > + char data[];/* Content following header */ > +}; > + > +struct B { > + int m; > + struct A a; > +}; > + > +struct C { > + int q; > + struct B b; > +}; > + > +struct A0 { > + int n; > + char data[0];/* Content following header */ > +}; > + > +struct B0 { > + int m; > + struct A0 a; > +}; > + > +struct C0 { > + int q; > + struct B0 b; > +}; > + > +struct A1 { > + int n; > + char data[1];/* Content following header */ > +}; > + > +struct B1 { > + int m; > + struct A1 a; > +}; > + > +struct C1 { > + int q; > + struct B1 b; > +}; > + > +struct An { > + int n; > + char data[8];/* Content following header */ > +}; > + > +struct Bn { > + int m; > + struct An a; > +}; > + > +struct Cn { > + int q; > + struct Bn b; > +}; > + > +volatile void *magic1, *magic2; > + > +int main(int argc, char *argv[]) > +{ > + struct B *outer; > + struct C *outest; > + > + /* Make sure optimization can't find some other object size. */ > + outer = (void *)magic1; > + outest = (void *)magic2; > + > + expect(__builtin_object_size(&outer->a, 1), -1); > + expect(__builtin_object_size(&outest->b, 1), -1); > + expect(__builtin_object_size(&outest->b.a, 1), -1); > + > + struct B0 *outer0; > + struct C0 *outest0; > + > + /* Make sure optimization can't find some other object size. */ > + outer0 = (void *)magic1; > + outest0 = (void *)magic2; > + > + expect(__builtin_object_size(&outer0->a, 1), -1); > + expect(__builtin_object_size(&outest0->b, 1), -1); > + expect(__builtin_object_size(&outest0->b.a, 1), -1); > + > + struct B1 *outer1; > + struct C1 *outest1; > + > + /* Make sure optimization can't find some other object size. */ > + outer1 = (void *)magic1; > + outest1 = (void *)magic2; > + > + expect(__builtin_object_size(&outer1->a, 1), -1); > + expect(__builtin_object_size(&outest1->b, 1), -1); > + expect(__builtin_object_size(&outest1->b.a, 1), -1); > + > + struct Bn *outern; > + struct Cn *outestn; > + > + /* Make sure optimization can't find some other object size. */ > + outern = (void *)magic1; > + outestn = (void *)magic2; > + > + expect(__builtin_object_size(&outern->a, 1), sizeof(outern->a)); > + expect(__builtin_object_size(&outestn->b, 1), sizeof(outestn->b)); > + expect(__builtin_object_size(&outestn->b.a, 1), sizeof(outestn->b.a)); > + > + if (n_fails > 0) > + __builtin_abort (); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c > new file mode 100644 > index 00000000000..aaae99b8d67 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c > @@ -0,0 +1,135 @@ > +/* PR 101832: > + GCC extension accepts the case when a struct with a flexible array member > + is embedded into another struct (possibly recursively). > + __builtin_object_size will treat such struct as flexible size per > + -fstrict-flex-arrays. */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -fstrict-flex-arrays=2" } */ > + > +#include > + > +unsigned n_fails = 0; > + > +#define expect(p, _v) do { \ > + size_t v = _v; \ > + if (p == v) \ > + printf("ok: %s == %zd\n", #p, p); \ > + else {\ > + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ > + n_fails++; \ > + } \ > +} while (0); > + > +struct A { > + int n; > + char data[];/* Content following header */ > +}; > + > +struct B { > + int m; > + struct A a; > +}; > + > +struct C { > + int q; > + struct B b; > +}; > + > +struct A0 { > + int n; > + char data[0];/* Content following header */ > +}; > + > +struct B0 { > + int m; > + struct A0 a; > +}; > + > +struct C0 { > + int q; > + struct B0 b; > +}; > + > +struct A1 { > + int n; > + char data[1];/* Content following header */ > +}; > + > +struct B1 { > + int m; > + struct A1 a; > +}; > + > +struct C1 { > + int q; > + struct B1 b; > +}; > + > +struct An { > + int n; > + char data[8];/* Content following header */ > +}; > + > +struct Bn { > + int m; > + struct An a; > +}; > + > +struct Cn { > + int q; > + struct Bn b; > +}; > + > +volatile void *magic1, *magic2; > + > +int main(int argc, char *argv[]) > +{ > + struct B *outer; > + struct C *outest; > + > + /* Make sure optimization can't find some other object size. */ > + outer = (void *)magic1; > + outest = (void *)magic2; > + > + expect(__builtin_object_size(&outer->a, 1), -1); > + expect(__builtin_object_size(&outest->b, 1), -1); > + expect(__builtin_object_size(&outest->b.a, 1), -1); > + > + struct B0 *outer0; > + struct C0 *outest0; > + > + /* Make sure optimization can't find some other object size. */ > + outer0 = (void *)magic1; > + outest0 = (void *)magic2; > + > + expect(__builtin_object_size(&outer0->a, 1), -1); > + expect(__builtin_object_size(&outest0->b, 1), -1); > + expect(__builtin_object_size(&outest0->b.a, 1), -1); > + > + struct B1 *outer1; > + struct C1 *outest1; > + > + /* Make sure optimization can't find some other object size. */ > + outer1 = (void *)magic1; > + outest1 = (void *)magic2; > + > + expect(__builtin_object_size(&outer1->a, 1), sizeof(outer1->a)); > + expect(__builtin_object_size(&outest1->b, 1), sizeof(outest1->b)); > + expect(__builtin_object_size(&outest1->b.a, 1), sizeof(outest1->b.a)); > + > + struct Bn *outern; > + struct Cn *outestn; > + > + /* Make sure optimization can't find some other object size. */ > + outern = (void *)magic1; > + outestn = (void *)magic2; > + > + expect(__builtin_object_size(&outern->a, 1), sizeof(outern->a)); > + expect(__builtin_object_size(&outestn->b, 1), sizeof(outestn->b)); > + expect(__builtin_object_size(&outestn->b.a, 1), sizeof(outestn->b.a)); > + > + if (n_fails > 0) > + __builtin_abort (); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c > new file mode 100644 > index 00000000000..424264e2acd > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c > @@ -0,0 +1,135 @@ > +/* PR 101832: > + GCC extension accepts the case when a struct with a flexible array member > + is embedded into another struct (possibly recursively). > + __builtin_object_size will treat such struct as flexible size per > + -fstrict-flex-arrays. */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -fstrict-flex-arrays=3" } */ > + > +#include > + > +unsigned n_fails = 0; > + > +#define expect(p, _v) do { \ > + size_t v = _v; \ > + if (p == v) \ > + printf("ok: %s == %zd\n", #p, p); \ > + else {\ > + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ > + n_fails++; \ > + } \ > +} while (0); > + > +struct A { > + int n; > + char data[];/* Content following header */ > +}; > + > +struct B { > + int m; > + struct A a; > +}; > + > +struct C { > + int q; > + struct B b; > +}; > + > +struct A0 { > + int n; > + char data[0];/* Content following header */ > +}; > + > +struct B0 { > + int m; > + struct A0 a; > +}; > + > +struct C0 { > + int q; > + struct B0 b; > +}; > + > +struct A1 { > + int n; > + char data[1];/* Content following header */ > +}; > + > +struct B1 { > + int m; > + struct A1 a; > +}; > + > +struct C1 { > + int q; > + struct B1 b; > +}; > + > +struct An { > + int n; > + char data[8];/* Content following header */ > +}; > + > +struct Bn { > + int m; > + struct An a; > +}; > + > +struct Cn { > + int q; > + struct Bn b; > +}; > + > +volatile void *magic1, *magic2; > + > +int main(int argc, char *argv[]) > +{ > + struct B *outer; > + struct C *outest; > + > + /* Make sure optimization can't find some other object size. */ > + outer = (void *)magic1; > + outest = (void *)magic2; > + > + expect(__builtin_object_size(&outer->a, 1), -1); > + expect(__builtin_object_size(&outest->b, 1), -1); > + expect(__builtin_object_size(&outest->b.a, 1), -1); > + > + struct B0 *outer0; > + struct C0 *outest0; > + > + /* Make sure optimization can't find some other object size. */ > + outer0 = (void *)magic1; > + outest0 = (void *)magic2; > + > + expect(__builtin_object_size(&outer0->a, 1), sizeof(outer0->a)); > + expect(__builtin_object_size(&outest0->b, 1), sizeof(outest0->b)); > + expect(__builtin_object_size(&outest0->b.a, 1), sizeof(outest0->b.a)); > + > + struct B1 *outer1; > + struct C1 *outest1; > + > + /* Make sure optimization can't find some other object size. */ > + outer1 = (void *)magic1; > + outest1 = (void *)magic2; > + > + expect(__builtin_object_size(&outer1->a, 1), sizeof(outer1->a)); > + expect(__builtin_object_size(&outest1->b, 1), sizeof(outest1->b)); > + expect(__builtin_object_size(&outest1->b.a, 1), sizeof(outest1->b.a)); > + > + struct Bn *outern; > + struct Cn *outestn; > + > + /* Make sure optimization can't find some other object size. */ > + outern = (void *)magic1; > + outestn = (void *)magic2; > + > + expect(__builtin_object_size(&outern->a, 1), sizeof(outern->a)); > + expect(__builtin_object_size(&outestn->b, 1), sizeof(outestn->b)); > + expect(__builtin_object_size(&outestn->b.a, 1), sizeof(outestn->b.a)); > + > + if (n_fails > 0) > + __builtin_abort (); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c > new file mode 100644 > index 00000000000..8ed6980edf0 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c > @@ -0,0 +1,119 @@ > +/* PR 101832: > + GCC extension accepts the case when a struct with a flexible array member > + is embedded into another struct (possibly recursively). > + __builtin_object_size will treat such struct as flexible size per > + -fstrict-flex-arrays. */ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#include > + > +unsigned n_fails = 0; > + > +#define expect(p, _v) do { \ > + size_t v = _v; \ > + if (p == v) \ > + printf("ok: %s == %zd\n", #p, p); \ > + else {\ > + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ > + n_fails++; \ > + } \ > +} while (0); > + > +struct A { > + int n; > + char data[];/* Content following header */ > +}; > + > +struct B { > + int m; > + struct A a; > +}; > + > +struct C { > + int q; > + struct B b; > +}; > + > +struct A0 { > + int n; > + char data[0];/* Content following header */ > +}; > + > +struct B0 { > + int m; > + struct A0 a; > +}; > + > +struct C0 { > + int q; > + struct B0 b; > +}; > + > +struct A1 { > + int n; > + char data[1];/* Content following header */ > +}; > + > +struct B1 { > + int m; > + struct A1 a; > +}; > + > +struct C1 { > + int q; > + struct B1 b; > +}; > + > +struct An { > + int n; > + char data[8];/* Content following header */ > +}; > + > +struct Bn { > + int m; > + struct An a; > +}; > + > +struct Cn { > + int q; > + struct Bn b; > +}; > + > +volatile void *magic1, *magic2; > + > +int main(int argc, char *argv[]) > +{ > + struct B *outer = (void *)magic1; > + struct C *outest = (void *)magic2; > + > + expect(__builtin_object_size(&outer->a, 1), -1); > + expect(__builtin_object_size(&outest->b, 1), -1); > + expect(__builtin_object_size(&outest->b.a, 1), -1); > + > + struct B0 *outer0 = (void *)magic1; > + struct C0 *outest0 = (void *)magic2; > + > + expect(__builtin_object_size(&outer0->a, 1), -1); > + expect(__builtin_object_size(&outest0->b, 1), -1); > + expect(__builtin_object_size(&outest0->b.a, 1), -1); > + > + struct B1 *outer1 = (void *)magic1; > + struct C1 *outest1 = (void *)magic2; > + > + expect(__builtin_object_size(&outer1->a, 1), -1); > + expect(__builtin_object_size(&outest1->b, 1), -1); > + expect(__builtin_object_size(&outest1->b.a, 1), -1); > + > + struct Bn *outern = (void *)magic1; > + struct Cn *outestn = (void *)magic2; > + > + expect(__builtin_object_size(&outern->a, 1), -1); > + expect(__builtin_object_size(&outestn->b, 1), -1); > + expect(__builtin_object_size(&outestn->b.a, 1), -1); > + > + if (n_fails > 0) > + __builtin_abort (); > + > + return 0; > +} > diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc > index 9a936a91983..56b78ca2a8c 100644 > --- a/gcc/tree-object-size.cc > +++ b/gcc/tree-object-size.cc > @@ -500,6 +500,42 @@ decl_init_size (tree decl, bool min) > return size; > } > > +/* Determine whether TYPE is a structure with a flexible array member > + per -fstrict-flex-array or a union containing such a structure > + (possibly recursively). */ > +static bool > +flexible_size_type_p (const_tree type) > +{ > + tree x = NULL_TREE; > + tree last = NULL_TREE; > + switch (TREE_CODE (type)) > + { > + case RECORD_TYPE: > + for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x)) > + if (TREE_CODE (x) == FIELD_DECL) > + last = x; > + if (last == NULL_TREE) > + return false; > + if (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE > + && !DECL_NOT_FLEXARRAY (last)) > + return true; > + else if (TREE_CODE (TREE_TYPE (last)) == RECORD_TYPE > + || TREE_CODE (TREE_TYPE (last)) == UNION_TYPE) > + return flexible_size_type_p (TREE_TYPE (last)); For types with many members this can become quite slow (IIRC we had bugs about similar walks of all fields in types), and this function looks like it's invoked multiple times on the same type per TU. In principle the property is fixed at the time we lay out a record type, so we might want to compute it at that time and record the result. > + return false; > + case UNION_TYPE: > + for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x)) > + { > + if (TREE_CODE (x) == FIELD_DECL > + && flexible_array_type_p (TREE_TYPE (x))) > + return true; > + } > + return false; > + default: > + return false; > + } > +} > + > /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR. > OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. > If unknown, return size_unknown (object_size_type). */ > @@ -633,45 +669,68 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, > v = NULL_TREE; > break; > case COMPONENT_REF: > - if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE) > + /* When the ref is not to an array, a record or a union, it > + will not have flexible size, compute the object size > + directly. */ > + if ((TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE) > + && (TREE_CODE (TREE_TYPE (v)) != RECORD_TYPE) > + && (TREE_CODE (TREE_TYPE (v)) != UNION_TYPE)) > { > v = NULL_TREE; > break; > } > - is_flexible_array_mem_ref = array_ref_flexible_size_p (v); > - while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) > - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - != UNION_TYPE > - && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - != QUAL_UNION_TYPE) > - break; > - else > - v = TREE_OPERAND (v, 0); > - if (TREE_CODE (v) == COMPONENT_REF > - && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - == RECORD_TYPE) > + /* if the record or union does not have flexible size > + compute the object size directly. */ > + if (TREE_CODE (TREE_TYPE (v)) == RECORD_TYPE > + || TREE_CODE (TREE_TYPE (v)) == UNION_TYPE) > { > - /* compute object size only if v is not a > - flexible array member. */ > - if (!is_flexible_array_mem_ref) > + if (!flexible_size_type_p (TREE_TYPE (v))) > { > v = NULL_TREE; > break; > } > - v = TREE_OPERAND (v, 0); > + else > + v = TREE_OPERAND (v, 0); > } > - while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) > - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - != UNION_TYPE > - && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - != QUAL_UNION_TYPE) > - break; > - else > - v = TREE_OPERAND (v, 0); > - if (v != pt_var) > - v = NULL_TREE; > else > - v = pt_var; > + { > + /* Now the ref is to an array type. */ > + is_flexible_array_mem_ref > + = array_ref_flexible_size_p (v); > + while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) > + if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > + != UNION_TYPE > + && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > + != QUAL_UNION_TYPE) > + break; > + else > + v = TREE_OPERAND (v, 0); > + if (TREE_CODE (v) == COMPONENT_REF > + && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > + == RECORD_TYPE) > + { > + /* compute object size only if v is not a > + flexible array member. */ > + if (!is_flexible_array_mem_ref) > + { > + v = NULL_TREE; > + break; > + } > + v = TREE_OPERAND (v, 0); > + } > + while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) > + if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > + != UNION_TYPE > + && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > + != QUAL_UNION_TYPE) > + break; > + else > + v = TREE_OPERAND (v, 0); > + if (v != pt_var) > + v = NULL_TREE; > + else > + v = pt_var; > + } > break; > default: > v = pt_var; > -- Richard Biener SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman; HRB 36809 (AG Nuernberg)