From: Qing Zhao <qing.zhao@oracle.com>
To: richard Sandiford <richard.sandiford@arm.com>,
Richard Biener <rguenther@suse.de>,
Kees Cook <keescook@chromium.org>
Cc: Gcc-patches Qing Zhao via <gcc-patches@gcc.gnu.org>
Subject: [patch for gcc12 stage1][version 2] add -ftrivial-auto-var-init and variable attribute "uninitialized" to gcc
Date: Wed, 24 Mar 2021 16:21:49 -0500 [thread overview]
Message-ID: <0CE28536-176B-44E1-BDC6-3942739B829C@oracle.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 10521 bytes --]
Hi,
This is the 2nd version of the patch for the new security feature for GCC.
Could you please take a look at it and let me know any comments and issues.
Thanks.
Qing
******compared to Version 1, this version added the following new features to address Kees’s comments:
1. correctly handle VLA inside a structure for pattern initialization.
In tree.c (build_pattern_cst):
+ /* if the field is a variable length array, it should be the last
+ field of the record, and no need to initialize. */
+ if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
+ && TYPE_SIZE (TREE_TYPE (field)) == NULL_TREE
+ && ((TYPE_DOMAIN (TREE_TYPE (field)) != NULL_TREE
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field)))
+ == NULL_TREE)
+ || TYPE_DOMAIN (TREE_TYPE (field)) == NULL_TREE))
+ continue;
2. initialize all paddings to zero when -ftrivial-auto-var-init is present.
In expr.c (store_constructor):
Clear the whole structure when
-ftrivial-auto-var-init and the structure has paddings.
In gimplify.c (gimplify_init_constructor):
Clear the whole structure when
-ftrivial-auto-var-init and the structure has paddings.
As agreed with Kees, treat the issue related to auto variables outside of the cases and inside the switch as a low priority one.
3. Add the following new testing cases for the above 1 and 2:
* c-c++-common/auto-init-13.c: New test.
* c-c++-common/auto-init-14.c: New test.
* gcc.target/aarch64/auto-init-9.c: New test.
* gcc.target/aarch64/auto-init-10.c: New test.
* gcc.target/aarch64/auto-init-11.c: New test.
* gcc.target/aarch64/auto-init-12.c: New test.
* gcc.target/aarch64/auto-init-13.c: New test.
* gcc.target/aarch64/auto-init-14.c: New test.
* gcc.target/aarch64/auto-init-15.c: New test.
* gcc.target/aarch64/auto-init-16.c: New test.
* gcc.target/aarch64/auto-init-17.c: New test.
* gcc.target/aarch64/auto-init-18.c: New test.
* gcc.target/aarch64/auto-init-19.c: New test.
* gcc.target/aarch64/auto-init-20.c: New test.
* gcc.target/i386/auto-init-9.c: New test.
* gcc.target/i386/auto-init-10.c: New test.
* gcc.target/i386/auto-init-11.c: New test.
* gcc.target/i386/auto-init-12.c: New test.
* gcc.target/i386/auto-init-13.c: New test.
* gcc.target/i386/auto-init-14.c: New test.
* gcc.target/i386/auto-init-15.c: New test.
* gcc.target/i386/auto-init-16.c: New test.
* gcc.target/i386/auto-init-17.c: New test.
* gcc.target/i386/auto-init-18.c: New test.
* gcc.target/i386/auto-init-19.c: New test.
* gcc.target/i386/auto-init-20.c: New test.
4. Update the default approach as D, then when specify -ftrivial-auto-var-init, the default approach is the “.DEFERRED_INIT”
Approach. No need to add -fauto-var-init-approach=D anymore.
If we need to compare approach A and D, we can add -fauto-var-init-approach=A to get that implementation.
5. Delete all -fauto-var-init-approach=D in the testing cases.
****** others are the same as Version 1, please see the version 1 description at:
https://gcc.gnu.org/pipermail/gcc-patches/2021-February/565581.html
*******Changelog:
gcc/:
2021-03-24 qing zhao <qing.zhao@oracle.com>
* common.opt (ftrivial-auto-var-init=): New.
(fauto-var-init-approach=): Likewise.
* doc/extend.texi: Document the uninitialized attribute.
* doc/invoke.texi: Document -ftrivial-auto-var-init.
* expr.c (store_constructor): Clear the whole structure when
-ftrivial-auto-var-init and the structure has paddings.
* flag-types.h (enum auto_init_type): New enumerated type
auto_init_type.
(enum auto_init_approach): New enumerated type auto_init_approach.
* gimple.h (enum gf_mask): Add GF_CALL_MEMSET_FOR_UNINIT case.
(gimple_call_set_memset_for_uninit): New function.
(gimple_call_memset_for_uninit_p): Likewise.
* gimplify.c (gimplify_vla_decl): Add initialization to vla per users'
requests.
(build_deferred_init): New function.
(gimple_add_init_for_auto_var): Likewise.
(gimplify_decl_expr): Add initialization to automatic variables per
users' requests.
(gimplify_init_constructor): Clear the whole structure when
-ftrivial-auto-var-init and the structure has paddings.
* internal-fn.c (expand_DEFERRED_INIT): New function.
* internal-fn.def (DEFERRED_INIT): New internal function.
* tree-cfg.c (verify_gimple_call): Skip calls to DEFERRED_INIT.
* tree-core.h (tree_decl_with_vis): Add uninitialized field.
* tree-sra.c (sra_stats): Add two new fields deferred_init and
subtree_deferred_init.
(generate_subtree_deferred_init): New function.
(sra_modify_deferred_init): Likewise.
(sra_modify_function_body): Handle calls to DEFERRED_INIT specially.
* tree-ssa-structalias.c (find_func_aliases_for_deferred_init): New
function.
(find_func_aliases_for_call): Handle calls to DEFERRED_INIT specially.
* tree-ssa-uninit.c (warn_uninit): Handle calls to DEFERRED_INIT
specially.
(check_defs): Handle calls to DEFERRED_INIT and MEMSET for uninitialized
variable specially.
(warn_uninitialized_vars): Handle calls to DEFERRED_INIT specially.
* tree-ssa.c (ssa_undefined_value_p): Handle calls to DEFERRED_INIT
specially.
* tree.c (build_pattern_cst): New function.
(type_has_padding): Likewise.
* tree.h (DECL_UNINITIALIZED): New macro.
(build_pattern_cst): New declaration.
(type_has_padding): Likewise.
gcc/c-family/:
2021-03-24 qing zhao <qing.zhao@oracle.com>
* c-attribs.c (handle_uninitialized_attribute): New function.
(c_common_attribute_table): Add "uninitialized" attribute.
gcc/testsuite/:
2021-03-24 qing zhao <qing.zhao@oracle.com>
* c-c++-common/auto-init-1.c: New test.
* c-c++-common/auto-init-10.c: New test.
* c-c++-common/auto-init-11.c: New test.
* c-c++-common/auto-init-12.c: New test.
* c-c++-common/auto-init-13.c: New test.
* c-c++-common/auto-init-14.c: New test.
* c-c++-common/auto-init-2.c: New test.
* c-c++-common/auto-init-3.c: New test.
* c-c++-common/auto-init-4.c: New test.
* c-c++-common/auto-init-5.c: New test.
* c-c++-common/auto-init-6.c: New test.
* c-c++-common/auto-init-7.c: New test.
* c-c++-common/auto-init-8.c: New test.
* c-c++-common/auto-init-9.c: New test.
* c-c++-common/auto-init-esra.c: New test.
* g++.dg/auto-init-uninit-pred-1_a.C: New test.
* g++.dg/auto-init-uninit-pred-1_b.C: New test.
* g++.dg/auto-init-uninit-pred-2_a.C: New test.
* g++.dg/auto-init-uninit-pred-2_b.C: New test.
* g++.dg/auto-init-uninit-pred-3_a.C: New test.
* g++.dg/auto-init-uninit-pred-3_b.C: New test.
* g++.dg/auto-init-uninit-pred-4.C: New test.
* g++.dg/auto-init-uninit-pred-loop-1_a.cc: New test.
* g++.dg/auto-init-uninit-pred-loop-1_b.cc: New test.
* g++.dg/auto-init-uninit-pred-loop-1_c.cc: New test.
* g++.dg/auto-init-uninit-pred-loop_1.cc: New test.
* gcc.dg/auto-init-uninit-1.c: New test.
* gcc.dg/auto-init-uninit-11.c: New test.
* gcc.dg/auto-init-uninit-12.c: New test.
* gcc.dg/auto-init-uninit-13.c: New test.
* gcc.dg/auto-init-uninit-14.c: New test.
* gcc.dg/auto-init-uninit-15.c: New test.
* gcc.dg/auto-init-uninit-16.c: New test.
* gcc.dg/auto-init-uninit-17.c: New test.
* gcc.dg/auto-init-uninit-18.c: New test.
* gcc.dg/auto-init-uninit-19.c: New test.
* gcc.dg/auto-init-uninit-2.c: New test.
* gcc.dg/auto-init-uninit-20.c: New test.
* gcc.dg/auto-init-uninit-21.c: New test.
* gcc.dg/auto-init-uninit-22.c: New test.
* gcc.dg/auto-init-uninit-23.c: New test.
* gcc.dg/auto-init-uninit-24.c: New test.
* gcc.dg/auto-init-uninit-25.c: New test.
* gcc.dg/auto-init-uninit-26.c: New test.
* gcc.dg/auto-init-uninit-3.c: New test.
* gcc.dg/auto-init-uninit-34.c: New test.
* gcc.dg/auto-init-uninit-36.c: New test.
* gcc.dg/auto-init-uninit-37.c: New test.
* gcc.dg/auto-init-uninit-4.c: New test.
* gcc.dg/auto-init-uninit-5.c: New test.
* gcc.dg/auto-init-uninit-6.c: New test.
* gcc.dg/auto-init-uninit-8.c: New test.
* gcc.dg/auto-init-uninit-9.c: New test.
* gcc.dg/auto-init-uninit-A.c: New test.
* gcc.dg/auto-init-uninit-B.c: New test.
* gcc.dg/auto-init-uninit-C.c: New test.
* gcc.dg/auto-init-uninit-H.c: New test.
* gcc.dg/auto-init-uninit-I.c: New test.
* gcc.target/aarch64/auto-init-1.c: New test.
* gcc.target/aarch64/auto-init-10.c: New test.
* gcc.target/aarch64/auto-init-11.c: New test.
* gcc.target/aarch64/auto-init-12.c: New test.
* gcc.target/aarch64/auto-init-13.c: New test.
* gcc.target/aarch64/auto-init-14.c: New test.
* gcc.target/aarch64/auto-init-15.c: New test.
* gcc.target/aarch64/auto-init-16.c: New test.
* gcc.target/aarch64/auto-init-17.c: New test.
* gcc.target/aarch64/auto-init-18.c: New test.
* gcc.target/aarch64/auto-init-19.c: New test.
* gcc.target/aarch64/auto-init-2.c: New test.
* gcc.target/aarch64/auto-init-20.c: New test.
* gcc.target/aarch64/auto-init-3.c: New test.
* gcc.target/aarch64/auto-init-4.c: New test.
* gcc.target/aarch64/auto-init-5.c: New test.
* gcc.target/aarch64/auto-init-6.c: New test.
* gcc.target/aarch64/auto-init-7.c: New test.
* gcc.target/aarch64/auto-init-8.c: New test.
* gcc.target/aarch64/auto-init-9.c: New test.
* gcc.target/i386/auto-init-1.c: New test.
* gcc.target/i386/auto-init-10.c: New test.
* gcc.target/i386/auto-init-11.c: New test.
* gcc.target/i386/auto-init-12.c: New test.
* gcc.target/i386/auto-init-13.c: New test.
* gcc.target/i386/auto-init-14.c: New test.
* gcc.target/i386/auto-init-15.c: New test.
* gcc.target/i386/auto-init-16.c: New test.
* gcc.target/i386/auto-init-17.c: New test.
* gcc.target/i386/auto-init-18.c: New test.
* gcc.target/i386/auto-init-19.c: New test.
* gcc.target/i386/auto-init-2.c: New test.
* gcc.target/i386/auto-init-20.c: New test.
* gcc.target/i386/auto-init-3.c: New test.
* gcc.target/i386/auto-init-4.c: New test.
* gcc.target/i386/auto-init-5.c: New test.
* gcc.target/i386/auto-init-6.c: New test.
* gcc.target/i386/auto-init-7.c: New test.
* gcc.target/i386/auto-init-8.c: New test.
* gcc.target/i386/auto-init-9.c: New test.
******The complete patch is attached as following:
[-- Attachment #2: 0001-add-ftrivial-auto-var-init-and-variable-attribute-un.patch --]
[-- Type: application/octet-stream, Size: 162686 bytes --]
From 481c1b6b36ebd47fa95f87a2490132636b443c77 Mon Sep 17 00:00:00 2001
From: qing zhao <qing.zhao@oracle.com>
Date: Wed, 24 Mar 2021 14:54:43 +0000
Subject: [PATCH] add -ftrivial-auto-var-init and variable attribute
uninitialized to gcc.
gcc/:
2021-03-24 qing zhao <qing.zhao@oracle.com>
* common.opt (ftrivial-auto-var-init=): New.
(fauto-var-init-approach=): Likewise.
* doc/extend.texi: Document the uninitialized attribute.
* doc/invoke.texi: Document -ftrivial-auto-var-init.
* expr.c (store_constructor): Clear the whole structure when
-ftrivial-auto-var-init and the structure has paddings.
* flag-types.h (enum auto_init_type): New enumerated type
auto_init_type.
(enum auto_init_approach): New enumerated type auto_init_approach.
* gimple.h (enum gf_mask): Add GF_CALL_MEMSET_FOR_UNINIT case.
(gimple_call_set_memset_for_uninit): New function.
(gimple_call_memset_for_uninit_p): Likewise.
* gimplify.c (gimplify_vla_decl): Add initialization to vla per users'
requests.
(build_deferred_init): New function.
(gimple_add_init_for_auto_var): Likewise.
(gimplify_decl_expr): Add initialization to automatic variables per
users' requests.
(gimplify_init_constructor): Clear the whole structure when
-ftrivial-auto-var-init and the structure has paddings.
* internal-fn.c (expand_DEFERRED_INIT): New function.
* internal-fn.def (DEFERRED_INIT): New internal function.
* tree-cfg.c (verify_gimple_call): Skip calls to DEFERRED_INIT.
* tree-core.h (tree_decl_with_vis): Add uninitialized field.
* tree-sra.c (sra_stats): Add two new fields deferred_init and
subtree_deferred_init.
(generate_subtree_deferred_init): New function.
(sra_modify_deferred_init): Likewise.
(sra_modify_function_body): Handle calls to DEFERRED_INIT specially.
* tree-ssa-structalias.c (find_func_aliases_for_deferred_init): New
function.
(find_func_aliases_for_call): Handle calls to DEFERRED_INIT specially.
* tree-ssa-uninit.c (warn_uninit): Handle calls to DEFERRED_INIT
specially.
(check_defs): Handle calls to DEFERRED_INIT and MEMSET for uninitialized
variable specially.
(warn_uninitialized_vars): Handle calls to DEFERRED_INIT specially.
* tree-ssa.c (ssa_undefined_value_p): Handle calls to DEFERRED_INIT
specially.
* tree.c (build_pattern_cst): New function.
(type_has_padding): Likewise.
* tree.h (DECL_UNINITIALIZED): New macro.
(build_pattern_cst): New declaration.
(type_has_padding): Likewise.
gcc/c-family/:
2021-03-24 qing zhao <qing.zhao@oracle.com>
* c-attribs.c (handle_uninitialized_attribute): New function.
(c_common_attribute_table): Add "uninitialized" attribute.
gcc/testsuite/:
2021-03-24 qing zhao <qing.zhao@oracle.com>
* c-c++-common/auto-init-1.c: New test.
* c-c++-common/auto-init-10.c: New test.
* c-c++-common/auto-init-11.c: New test.
* c-c++-common/auto-init-12.c: New test.
* c-c++-common/auto-init-13.c: New test.
* c-c++-common/auto-init-14.c: New test.
* c-c++-common/auto-init-2.c: New test.
* c-c++-common/auto-init-3.c: New test.
* c-c++-common/auto-init-4.c: New test.
* c-c++-common/auto-init-5.c: New test.
* c-c++-common/auto-init-6.c: New test.
* c-c++-common/auto-init-7.c: New test.
* c-c++-common/auto-init-8.c: New test.
* c-c++-common/auto-init-9.c: New test.
* c-c++-common/auto-init-esra.c: New test.
* g++.dg/auto-init-uninit-pred-1_a.C: New test.
* g++.dg/auto-init-uninit-pred-1_b.C: New test.
* g++.dg/auto-init-uninit-pred-2_a.C: New test.
* g++.dg/auto-init-uninit-pred-2_b.C: New test.
* g++.dg/auto-init-uninit-pred-3_a.C: New test.
* g++.dg/auto-init-uninit-pred-3_b.C: New test.
* g++.dg/auto-init-uninit-pred-4.C: New test.
* g++.dg/auto-init-uninit-pred-loop-1_a.cc: New test.
* g++.dg/auto-init-uninit-pred-loop-1_b.cc: New test.
* g++.dg/auto-init-uninit-pred-loop-1_c.cc: New test.
* g++.dg/auto-init-uninit-pred-loop_1.cc: New test.
* gcc.dg/auto-init-uninit-1.c: New test.
* gcc.dg/auto-init-uninit-11.c: New test.
* gcc.dg/auto-init-uninit-12.c: New test.
* gcc.dg/auto-init-uninit-13.c: New test.
* gcc.dg/auto-init-uninit-14.c: New test.
* gcc.dg/auto-init-uninit-15.c: New test.
* gcc.dg/auto-init-uninit-16.c: New test.
* gcc.dg/auto-init-uninit-17.c: New test.
* gcc.dg/auto-init-uninit-18.c: New test.
* gcc.dg/auto-init-uninit-19.c: New test.
* gcc.dg/auto-init-uninit-2.c: New test.
* gcc.dg/auto-init-uninit-20.c: New test.
* gcc.dg/auto-init-uninit-21.c: New test.
* gcc.dg/auto-init-uninit-22.c: New test.
* gcc.dg/auto-init-uninit-23.c: New test.
* gcc.dg/auto-init-uninit-24.c: New test.
* gcc.dg/auto-init-uninit-25.c: New test.
* gcc.dg/auto-init-uninit-26.c: New test.
* gcc.dg/auto-init-uninit-3.c: New test.
* gcc.dg/auto-init-uninit-34.c: New test.
* gcc.dg/auto-init-uninit-36.c: New test.
* gcc.dg/auto-init-uninit-37.c: New test.
* gcc.dg/auto-init-uninit-4.c: New test.
* gcc.dg/auto-init-uninit-5.c: New test.
* gcc.dg/auto-init-uninit-6.c: New test.
* gcc.dg/auto-init-uninit-8.c: New test.
* gcc.dg/auto-init-uninit-9.c: New test.
* gcc.dg/auto-init-uninit-A.c: New test.
* gcc.dg/auto-init-uninit-B.c: New test.
* gcc.dg/auto-init-uninit-C.c: New test.
* gcc.dg/auto-init-uninit-H.c: New test.
* gcc.dg/auto-init-uninit-I.c: New test.
* gcc.target/aarch64/auto-init-1.c: New test.
* gcc.target/aarch64/auto-init-10.c: New test.
* gcc.target/aarch64/auto-init-11.c: New test.
* gcc.target/aarch64/auto-init-12.c: New test.
* gcc.target/aarch64/auto-init-13.c: New test.
* gcc.target/aarch64/auto-init-14.c: New test.
* gcc.target/aarch64/auto-init-15.c: New test.
* gcc.target/aarch64/auto-init-16.c: New test.
* gcc.target/aarch64/auto-init-17.c: New test.
* gcc.target/aarch64/auto-init-18.c: New test.
* gcc.target/aarch64/auto-init-19.c: New test.
* gcc.target/aarch64/auto-init-2.c: New test.
* gcc.target/aarch64/auto-init-20.c: New test.
* gcc.target/aarch64/auto-init-3.c: New test.
* gcc.target/aarch64/auto-init-4.c: New test.
* gcc.target/aarch64/auto-init-5.c: New test.
* gcc.target/aarch64/auto-init-6.c: New test.
* gcc.target/aarch64/auto-init-7.c: New test.
* gcc.target/aarch64/auto-init-8.c: New test.
* gcc.target/aarch64/auto-init-9.c: New test.
* gcc.target/i386/auto-init-1.c: New test.
* gcc.target/i386/auto-init-10.c: New test.
* gcc.target/i386/auto-init-11.c: New test.
* gcc.target/i386/auto-init-12.c: New test.
* gcc.target/i386/auto-init-13.c: New test.
* gcc.target/i386/auto-init-14.c: New test.
* gcc.target/i386/auto-init-15.c: New test.
* gcc.target/i386/auto-init-16.c: New test.
* gcc.target/i386/auto-init-17.c: New test.
* gcc.target/i386/auto-init-18.c: New test.
* gcc.target/i386/auto-init-19.c: New test.
* gcc.target/i386/auto-init-2.c: New test.
* gcc.target/i386/auto-init-20.c: New test.
* gcc.target/i386/auto-init-3.c: New test.
* gcc.target/i386/auto-init-4.c: New test.
* gcc.target/i386/auto-init-5.c: New test.
* gcc.target/i386/auto-init-6.c: New test.
* gcc.target/i386/auto-init-7.c: New test.
* gcc.target/i386/auto-init-8.c: New test.
* gcc.target/i386/auto-init-9.c: New test.
---
gcc/c-family/c-attribs.c | 21 ++
gcc/common.opt | 29 +++
gcc/doc/extend.texi | 16 ++
gcc/doc/invoke.texi | 34 ++-
gcc/expr.c | 17 +-
gcc/flag-types.h | 12 ++
gcc/gimple.h | 24 +++
gcc/gimplify.c | 191 +++++++++++++++++
gcc/internal-fn.c | 24 +++
gcc/internal-fn.def | 5 +
gcc/testsuite/c-c++-common/auto-init-1.c | 39 ++++
gcc/testsuite/c-c++-common/auto-init-10.c | 17 ++
gcc/testsuite/c-c++-common/auto-init-11.c | 14 ++
gcc/testsuite/c-c++-common/auto-init-12.c | 14 ++
gcc/testsuite/c-c++-common/auto-init-13.c | 23 ++
gcc/testsuite/c-c++-common/auto-init-14.c | 23 ++
gcc/testsuite/c-c++-common/auto-init-2.c | 39 ++++
gcc/testsuite/c-c++-common/auto-init-3.c | 19 ++
gcc/testsuite/c-c++-common/auto-init-4.c | 19 ++
gcc/testsuite/c-c++-common/auto-init-5.c | 21 ++
gcc/testsuite/c-c++-common/auto-init-6.c | 21 ++
gcc/testsuite/c-c++-common/auto-init-7.c | 35 +++
gcc/testsuite/c-c++-common/auto-init-8.c | 35 +++
gcc/testsuite/c-c++-common/auto-init-9.c | 17 ++
gcc/testsuite/c-c++-common/auto-init-esra.c | 35 +++
gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C | 63 ++++++
gcc/testsuite/g++.dg/auto-init-uninit-pred-1_b.C | 63 ++++++
gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C | 62 ++++++
gcc/testsuite/g++.dg/auto-init-uninit-pred-2_b.C | 62 ++++++
gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C | 77 +++++++
gcc/testsuite/g++.dg/auto-init-uninit-pred-3_b.C | 87 ++++++++
gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C | 16 ++
.../g++.dg/auto-init-uninit-pred-loop-1_a.cc | 21 ++
.../g++.dg/auto-init-uninit-pred-loop-1_b.cc | 21 ++
.../g++.dg/auto-init-uninit-pred-loop-1_c.cc | 23 ++
.../g++.dg/auto-init-uninit-pred-loop_1.cc | 21 ++
gcc/testsuite/gcc.dg/auto-init-uninit-1.c | 30 +++
gcc/testsuite/gcc.dg/auto-init-uninit-11.c | 42 ++++
gcc/testsuite/gcc.dg/auto-init-uninit-12.c | 12 ++
gcc/testsuite/gcc.dg/auto-init-uninit-13.c | 10 +
gcc/testsuite/gcc.dg/auto-init-uninit-14.c | 20 ++
gcc/testsuite/gcc.dg/auto-init-uninit-15.c | 26 +++
gcc/testsuite/gcc.dg/auto-init-uninit-16.c | 23 ++
gcc/testsuite/gcc.dg/auto-init-uninit-17.c | 15 ++
gcc/testsuite/gcc.dg/auto-init-uninit-18.c | 24 +++
gcc/testsuite/gcc.dg/auto-init-uninit-19.c | 26 +++
gcc/testsuite/gcc.dg/auto-init-uninit-2.c | 52 +++++
gcc/testsuite/gcc.dg/auto-init-uninit-20.c | 18 ++
gcc/testsuite/gcc.dg/auto-init-uninit-21.c | 33 +++
gcc/testsuite/gcc.dg/auto-init-uninit-22.c | 69 ++++++
gcc/testsuite/gcc.dg/auto-init-uninit-23.c | 27 +++
gcc/testsuite/gcc.dg/auto-init-uninit-24.c | 10 +
gcc/testsuite/gcc.dg/auto-init-uninit-25.c | 23 ++
gcc/testsuite/gcc.dg/auto-init-uninit-26.c | 23 ++
gcc/testsuite/gcc.dg/auto-init-uninit-3.c | 33 +++
gcc/testsuite/gcc.dg/auto-init-uninit-34.c | 58 +++++
gcc/testsuite/gcc.dg/auto-init-uninit-36.c | 238 +++++++++++++++++++++
gcc/testsuite/gcc.dg/auto-init-uninit-37.c | 154 +++++++++++++
gcc/testsuite/gcc.dg/auto-init-uninit-4.c | 52 +++++
gcc/testsuite/gcc.dg/auto-init-uninit-5.c | 39 ++++
gcc/testsuite/gcc.dg/auto-init-uninit-6.c | 47 ++++
gcc/testsuite/gcc.dg/auto-init-uninit-8.c | 32 +++
gcc/testsuite/gcc.dg/auto-init-uninit-9.c | 42 ++++
gcc/testsuite/gcc.dg/auto-init-uninit-A.c | 117 ++++++++++
gcc/testsuite/gcc.dg/auto-init-uninit-B.c | 15 ++
gcc/testsuite/gcc.dg/auto-init-uninit-C.c | 21 ++
gcc/testsuite/gcc.dg/auto-init-uninit-H.c | 33 +++
gcc/testsuite/gcc.dg/auto-init-uninit-I.c | 8 +
gcc/testsuite/gcc.target/aarch64/auto-init-1.c | 32 +++
gcc/testsuite/gcc.target/aarch64/auto-init-10.c | 18 ++
gcc/testsuite/gcc.target/aarch64/auto-init-11.c | 27 +++
gcc/testsuite/gcc.target/aarch64/auto-init-12.c | 27 +++
gcc/testsuite/gcc.target/aarch64/auto-init-13.c | 22 ++
gcc/testsuite/gcc.target/aarch64/auto-init-14.c | 20 ++
gcc/testsuite/gcc.target/aarch64/auto-init-15.c | 20 ++
gcc/testsuite/gcc.target/aarch64/auto-init-16.c | 22 ++
gcc/testsuite/gcc.target/aarch64/auto-init-17.c | 21 ++
gcc/testsuite/gcc.target/aarch64/auto-init-18.c | 21 ++
gcc/testsuite/gcc.target/aarch64/auto-init-19.c | 27 +++
gcc/testsuite/gcc.target/aarch64/auto-init-2.c | 37 ++++
gcc/testsuite/gcc.target/aarch64/auto-init-20.c | 27 +++
gcc/testsuite/gcc.target/aarch64/auto-init-3.c | 19 ++
gcc/testsuite/gcc.target/aarch64/auto-init-4.c | 19 ++
gcc/testsuite/gcc.target/aarch64/auto-init-5.c | 19 ++
gcc/testsuite/gcc.target/aarch64/auto-init-6.c | 21 ++
gcc/testsuite/gcc.target/aarch64/auto-init-7.c | 32 +++
gcc/testsuite/gcc.target/aarch64/auto-init-8.c | 33 +++
gcc/testsuite/gcc.target/aarch64/auto-init-9.c | 19 ++
gcc/testsuite/gcc.target/i386/auto-init-1.c | 32 +++
gcc/testsuite/gcc.target/i386/auto-init-10.c | 19 ++
gcc/testsuite/gcc.target/i386/auto-init-11.c | 30 +++
gcc/testsuite/gcc.target/i386/auto-init-12.c | 30 +++
gcc/testsuite/gcc.target/i386/auto-init-13.c | 22 ++
gcc/testsuite/gcc.target/i386/auto-init-14.c | 22 ++
gcc/testsuite/gcc.target/i386/auto-init-15.c | 22 ++
gcc/testsuite/gcc.target/i386/auto-init-16.c | 22 ++
gcc/testsuite/gcc.target/i386/auto-init-17.c | 23 ++
gcc/testsuite/gcc.target/i386/auto-init-18.c | 21 ++
gcc/testsuite/gcc.target/i386/auto-init-19.c | 26 +++
gcc/testsuite/gcc.target/i386/auto-init-2.c | 37 ++++
gcc/testsuite/gcc.target/i386/auto-init-20.c | 26 +++
gcc/testsuite/gcc.target/i386/auto-init-3.c | 20 ++
gcc/testsuite/gcc.target/i386/auto-init-4.c | 23 ++
gcc/testsuite/gcc.target/i386/auto-init-5.c | 19 ++
gcc/testsuite/gcc.target/i386/auto-init-6.c | 22 ++
gcc/testsuite/gcc.target/i386/auto-init-7.c | 32 +++
gcc/testsuite/gcc.target/i386/auto-init-8.c | 33 +++
gcc/testsuite/gcc.target/i386/auto-init-9.c | 19 ++
gcc/tree-cfg.c | 3 +
gcc/tree-core.h | 3 +-
gcc/tree-sra.c | 132 +++++++++++-
gcc/tree-ssa-structalias.c | 29 +++
gcc/tree-ssa-uninit.c | 30 +++
gcc/tree-ssa.c | 17 ++
gcc/tree.c | 204 ++++++++++++++++++
gcc/tree.h | 6 +
116 files changed, 4021 insertions(+), 18 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/auto-init-1.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-10.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-11.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-12.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-13.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-14.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-2.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-3.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-4.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-5.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-6.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-7.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-8.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-9.c
create mode 100644 gcc/testsuite/c-c++-common/auto-init-esra.c
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-1_b.C
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-2_b.C
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-3_b.C
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_a.cc
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_b.cc
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_c.cc
create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-loop_1.cc
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-1.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-11.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-12.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-13.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-14.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-15.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-16.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-17.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-18.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-19.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-2.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-20.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-21.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-22.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-23.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-24.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-25.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-26.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-3.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-34.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-36.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-37.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-4.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-5.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-6.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-8.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-9.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-A.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-B.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-C.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-H.c
create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-I.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-1.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-10.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-11.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-12.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-13.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-14.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-15.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-16.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-17.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-18.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-19.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-2.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-20.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-3.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-4.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-5.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-6.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-7.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-8.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-9.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-1.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-10.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-11.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-12.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-13.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-14.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-15.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-16.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-17.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-18.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-19.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-2.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-20.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-3.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-4.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-5.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-6.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-7.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-8.c
create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-9.c
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index c1f652d..2a69e07 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -81,6 +81,7 @@ static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
static tree handle_error_attribute (tree *, tree, tree, int, bool *);
static tree handle_used_attribute (tree *, tree, tree, int, bool *);
+static tree handle_uninitialized_attribute (tree *, tree, tree, int, bool *);
static tree handle_externally_visible_attribute (tree *, tree, tree, int,
bool *);
static tree handle_no_reorder_attribute (tree *, tree, tree, int,
@@ -329,6 +330,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_used_attribute, NULL },
{ "unused", 0, 0, false, false, false, false,
handle_unused_attribute, NULL },
+ { "uninitialized", 0, 0, true, false, false, false,
+ handle_uninitialized_attribute, NULL },
{ "retain", 0, 0, true, false, false, false,
handle_retain_attribute, NULL },
{ "externally_visible", 0, 0, true, false, false, false,
@@ -1589,6 +1592,24 @@ handle_retain_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
+/* Handle a "uninitialized" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_uninitialized_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (VAR_P (*node))
+ DECL_UNINITIALIZED (*node) = 1;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "externally_visible" attribute; arguments as in
struct attribute_spec.handler. */
diff --git a/gcc/common.opt b/gcc/common.opt
index c75dd36..d0fc7bb 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3049,6 +3049,35 @@ ftree-scev-cprop
Common Var(flag_tree_scev_cprop) Init(1) Optimization
Enable copy propagation of scalar-evolution information.
+ftrivial-auto-var-init=
+Common Joined RejectNegative Enum(auto_init_type) Var(flag_trivial_auto_var_init) Init(AUTO_INIT_UNINITIALIZED)
+-ftrivial-auto-var-init=[uninitialized|pattern|zero] Add initializations to automatic variables.
+
+Enum
+Name(auto_init_type) Type(enum auto_init_type) UnknownError(unrecognized automatic variable initialization type %qs)
+
+EnumValue
+Enum(auto_init_type) String(uninitialized) Value(AUTO_INIT_UNINITIALIZED)
+
+EnumValue
+Enum(auto_init_type) String(pattern) Value(AUTO_INIT_PATTERN)
+
+EnumValue
+Enum(auto_init_type) String(zero) Value(AUTO_INIT_ZERO)
+
+fauto-var-init-approach=
+Common Joined RejectNegative Enum(auto_init_approach) Var(flag_auto_init_approach) Init(AUTO_INIT_D))
+-fauto-var-init-approach=[A|D] Choose the approach to initialize automatic variables.
+
+Enum
+Name(auto_init_approach) Type(enum auto_init_approach) UnknownError(unrecognized automatic variable initialization approach %qs)
+
+EnumValue
+Enum(auto_init_approach) String(A) Value(AUTO_INIT_A)
+
+EnumValue
+Enum(auto_init_approach) String(D) Value(AUTO_INIT_D)
+
; -fverbose-asm causes extra commentary information to be produced in
; the generated assembly code (to make it more readable). This option
; is generally only of use to those who actually need to read the
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 0debf84..5c737d0 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -7519,6 +7519,22 @@ will be placed in new, unique sections.
This additional functionality requires Binutils version 2.36 or later.
+@item uninitialized
+@cindex @code{uninitialized} variable attribute
+This attribute, attached to a variable with automatic storage, means that
+the variable should not be automatically initialized by the compiler when
+the option @code{-ftrivial-auto-var-init} presents.
+
+With the option @code{-ftrivial-auto-var-init}, all the automatic variables
+that do not have explicit initializers will be initialized by the compiler.
+These additional compiler initializations might incur run-time overhead,
+sometimes dramatically. This attribute can be used to mark some variables
+to be excluded from such automatical initialization in order to reduce runtime
+overhead.
+
+This attribute has no effect when the option @code{-ftrivial-auto-var-init}
+does not present.
+
@item vector_size (@var{bytes})
@cindex @code{vector_size} variable attribute
This attribute specifies the vector size for the type of the declared
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ca204c7..0b80fcc 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -567,9 +567,9 @@ Objective-C and Objective-C++ Dialects}.
-ftree-parallelize-loops=@var{n} -ftree-pre -ftree-partial-pre -ftree-pta @gol
-ftree-reassoc -ftree-scev-cprop -ftree-sink -ftree-slsr -ftree-sra @gol
-ftree-switch-conversion -ftree-tail-merge @gol
--ftree-ter -ftree-vectorize -ftree-vrp -funconstrained-commons @gol
--funit-at-a-time -funroll-all-loops -funroll-loops @gol
--funsafe-math-optimizations -funswitch-loops @gol
+-ftree-ter -ftree-vectorize -ftree-vrp -ftrivial-auto-var-init @gol
+-funconstrained-commons -funit-at-a-time -funroll-all-loops @gol
+-funroll-loops -funsafe-math-optimizations -funswitch-loops @gol
-fipa-ra -fvariable-expansion-in-unroller -fvect-cost-model -fvpt @gol
-fweb -fwhole-program -fwpa -fuse-linker-plugin -fzero-call-used-regs @gol
--param @var{name}=@var{value}
@@ -11689,6 +11689,34 @@ Perform basic block vectorization on trees. This flag is enabled by default at
@option{-O3} and by @option{-ftree-vectorize}, @option{-fprofile-use},
and @option{-fauto-profile}.
+@item -ftrivial-auto-var-init=@var{choice}
+@opindex ftrivial-auto-var-init
+Initialize automatic variables with either a pattern or with zeroes to increase
+program security by preventing uninitialized memory disclosure and use.
+
+The three values of @var{choice} are:
+
+@itemize @bullet
+@item
+@samp{uninitialized} doesn't initialize any automatic variables.
+This is C and C++'s default.
+
+@item
+@samp{pattern} Initialize automatic variables with values which will likely
+transform logic bugs into crashes down the line, are easily recognized in a
+crash dump and without being values that programmers can rely on for useful
+program semantics.
+The values used for pattern initialization might be changed in the future.
+
+@item
+@samp{zero} Initialize automatic variables with zeroes.
+@end itemize
+
+The default is @samp{uninitialized}.
+
+You can control this behavior for a specific variable by using the variable
+attribute @code{uninitialized} (@pxref{Variable Attributes}).
+
@item -fvect-cost-model=@var{model}
@opindex fvect-cost-model
Alter the cost model used for vectorization. The @var{model} argument
diff --git a/gcc/expr.c b/gcc/expr.c
index 92035c7..4a3516e 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6566,14 +6566,19 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
cleared = 1;
}
- /* If the constructor has fewer fields than the structure or
- if we are initializing the structure to mostly zeros, clear
- the whole structure first. Don't do this if TARGET is a
- register whose mode size isn't equal to SIZE since
- clear_storage can't handle this case. */
+ /* If the constructor has fewer fields than the structure,
+ or if we are initializing the structure to mostly zeros,
+ or if the user requests to initialize automatic variables with
+ paddings inside the type,
+ we should clear the whole structure first.
+ Don't do this if TARGET is a register whose mode size isn't equal
+ SIZE since clear_storage can't handle this case. */
else if (known_size_p (size)
&& (((int) CONSTRUCTOR_NELTS (exp) != fields_length (type))
- || mostly_zeros_p (exp))
+ || mostly_zeros_p (exp)
+ || (flag_trivial_auto_var_init > AUTO_INIT_UNINITIALIZED
+ && !TREE_STATIC (exp)
+ && type_has_padding (type)))
&& (!REG_P (target)
|| known_eq (GET_MODE_SIZE (GET_MODE (target)), size)))
{
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index a038c8f..28e3231 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -242,6 +242,18 @@ enum vect_cost_model {
VECT_COST_MODEL_DEFAULT = 1
};
+/* Automatic variable initialization type. */
+enum auto_init_type {
+ AUTO_INIT_UNINITIALIZED = 0,
+ AUTO_INIT_PATTERN = 1,
+ AUTO_INIT_ZERO = 2
+};
+
+enum auto_init_approach {
+ AUTO_INIT_A = 0,
+ AUTO_INIT_D = 1
+};
+
/* Different instrumentation modes. */
enum sanitize_code {
/* AddressSanitizer. */
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 3ec86f5..8e947bc 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -150,6 +150,7 @@ enum gf_mask {
GF_CALL_BY_DESCRIPTOR = 1 << 10,
GF_CALL_NOCF_CHECK = 1 << 11,
GF_CALL_FROM_NEW_OR_DELETE = 1 << 12,
+ GF_CALL_MEMSET_FOR_UNINIT = 1 << 13,
GF_OMP_PARALLEL_COMBINED = 1 << 0,
GF_OMP_TASK_TASKLOOP = 1 << 0,
GF_OMP_TASK_TASKWAIT = 1 << 1,
@@ -3488,6 +3489,29 @@ gimple_call_alloca_for_var_p (gimple *s)
return (gc->subcode & GF_CALL_ALLOCA_FOR_VAR) != 0;
}
+/* If FOR_UNINIT is true, GIMPLE_CALL S is a call to builtin_memset that
+ is known to be emitted for unintialized VLA objects. */
+
+static inline void
+gimple_call_set_memset_for_uninit (gcall *s, bool for_uninit)
+{
+ if (for_uninit)
+ s->subcode |= GF_CALL_MEMSET_FOR_UNINIT;
+ else
+ s->subcode &= ~GF_CALL_MEMSET_FOR_UNINIT;
+}
+
+/* Return true if S is a call to builtin_memset emitted for uninitialized
+ VLA objects. */
+
+static inline bool
+gimple_call_memset_for_uninit_p (gimple *s)
+{
+ const gcall *gc = GIMPLE_CHECK2<gcall *> (s);
+ return (gc->subcode & GF_CALL_MEMSET_FOR_UNINIT) != 0;
+}
+
+
/* If BY_DESCRIPTOR_P is true, GIMPLE_CALL S is an indirect call for which
pointers to nested function are descriptors instead of trampolines. */
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 6da6698..fafd2e9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1716,6 +1716,116 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
gimplify_and_add (t, seq_p);
+ /* Add a call to memset or calls to memcpy to initialize this vla
+ when the user requested. */
+ if (!DECL_ARTIFICIAL (decl)
+ && VAR_P (decl)
+ && !DECL_EXTERNAL (decl)
+ && !TREE_STATIC (decl)
+ && !DECL_UNINITIALIZED (decl))
+ switch (flag_trivial_auto_var_init)
+ {
+ case AUTO_INIT_UNINITIALIZED:
+ break;
+ case AUTO_INIT_ZERO:
+ {
+ /* Generate a call to memset to initialize this vla. */
+ gcall *gs;
+ t = builtin_decl_implicit (BUILT_IN_MEMSET);
+ gs = gimple_build_call (t, 3, addr, integer_zero_node,
+ DECL_SIZE_UNIT (decl));
+ gimple_call_set_memset_for_uninit (gs, true);
+ gimplify_seq_add_stmt (seq_p, gs);
+ }
+ break;
+ case AUTO_INIT_PATTERN:
+ {
+ /* Generate the following sequence to initialize this vla:
+ if (DECL_SIZE_UNIT (decl) > 0) goto label_true;
+ else goto label_cont;
+ label_true:
+ {
+ element_type = TREE_TYPE (TREE_TYPE (decl));
+ size_of_element = DECL_SIZE_UNIT (element_type);
+ init_node = build_pattern_cst (element_type);
+ cur = addr;
+ offset = DECL_SIZE_UNIT (decl) - size_of_element;
+ end = addr + offset;
+
+ label_loop:
+ {
+ memcpy (cur, &init_node, size_of_element);
+ cur += size_of_element;
+ if (cur <= end) goto label_loop;
+ else goto label_cont;
+ }
+ }
+ label_cont:
+ */
+
+ tree size_of_element, element_type;
+ tree cur, end, offset;
+ tree init_node, addrof_init_node;
+ tree t;
+
+ tree label_true = create_artificial_label (UNKNOWN_LOCATION);
+ tree label_cont = create_artificial_label (UNKNOWN_LOCATION);
+ tree label_loop = create_artificial_label (UNKNOWN_LOCATION);
+
+ element_type = TREE_TYPE (TREE_TYPE (decl));
+
+ gcond *cond_stmt = gimple_build_cond (GT_EXPR, DECL_SIZE_UNIT (decl),
+ build_zero_cst (sizetype),
+ label_true,
+ label_cont);
+ gimplify_seq_add_stmt (seq_p, cond_stmt);
+ gimplify_seq_add_stmt (seq_p, gimple_build_label (label_true));
+
+ size_of_element = create_tmp_var (sizetype,
+ ".size_of_element");
+
+ init_node = create_tmp_var (element_type, ".init_node");
+ mark_addressable (init_node);
+ addrof_init_node = build_fold_addr_expr_loc (UNKNOWN_LOCATION,
+ init_node);
+
+ gimplify_assign (size_of_element, TYPE_SIZE_UNIT (element_type),
+ seq_p);
+ gimplify_assign (init_node, build_pattern_cst (element_type), seq_p);
+
+ cur = create_tmp_var (ptr_type, ".cur_addr");
+ end = create_tmp_var (ptr_type, ".end_addr");
+ offset = create_tmp_var (sizetype, ".offset");
+
+ gimplify_assign (cur, addr, seq_p);
+ gimplify_seq_add_stmt (seq_p,
+ gimple_build_assign (offset, MINUS_EXPR,
+ DECL_SIZE_UNIT (decl),
+ size_of_element));
+ gimplify_seq_add_stmt (seq_p,
+ gimple_build_assign (end, POINTER_PLUS_EXPR,
+ addr, offset));
+
+ gimplify_seq_add_stmt (seq_p, gimple_build_label (label_loop));
+
+ t = builtin_decl_implicit (BUILT_IN_MEMCPY);
+ gimplify_seq_add_stmt (seq_p,
+ gimple_build_call (t, 3, cur,
+ addrof_init_node,
+ size_of_element));
+ gimplify_seq_add_stmt (seq_p,
+ gimple_build_assign (cur, POINTER_PLUS_EXPR,
+ cur, size_of_element));
+ cond_stmt = gimple_build_cond (LE_EXPR, cur, end, label_loop,
+ label_cont);
+ gimplify_seq_add_stmt (seq_p, cond_stmt);
+ gimplify_seq_add_stmt (seq_p, gimple_build_label (label_cont));
+ }
+ break;
+ default:
+ gcc_assert (0);
+ }
+
/* Record the dynamic allocation associated with DECL if requested. */
if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
record_dynamic_alloc (decl);
@@ -1738,6 +1848,65 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
return NULL_TREE;
}
+
+/* Build a call to internal const function DEFERRED_INIT:
+ 1st argument: DECL;
+ 2nd argument: INIT_TYPE;
+
+ as DEFERRED_INIT (DECL, INIT_TYPE)
+
+ DEFERRED_INIT is defined as:
+ DEF_INTERNAL_FN(DEFERRED_INIT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL). */
+
+static gimple *
+build_deferred_init (tree decl,
+ enum auto_init_type init_type)
+{
+ tree init_type_node
+ = build_int_cst (integer_type_node, (int) init_type);
+ return gimple_build_call_internal (IFN_DEFERRED_INIT, 2,
+ decl, init_type_node);
+}
+
+/* Generate initialization to automatic variable DECL based on INIT_TYPE. */
+static void
+gimple_add_init_for_auto_var (tree decl,
+ enum auto_init_type init_type,
+ enum auto_init_approach init_approach,
+ gimple_seq *seq_p)
+{
+ gcc_assert (VAR_P (decl) && !DECL_EXTERNAL (decl) && !TREE_STATIC (decl));
+ switch (init_type)
+ {
+ case AUTO_INIT_UNINITIALIZED:
+ gcc_assert (0);
+ break;
+ case AUTO_INIT_PATTERN:
+ case AUTO_INIT_ZERO:
+ if (init_approach == AUTO_INIT_A)
+ {
+ tree init = (init_type == AUTO_INIT_PATTERN)
+ ? build_pattern_cst (TREE_TYPE (decl)) :
+ build_zero_cst (TREE_TYPE (decl));
+ init = build2 (INIT_EXPR, void_type_node, decl, init);
+ gimplify_and_add (init, seq_p);
+ ggc_free (init);
+ }
+ else if (init_approach == AUTO_INIT_D)
+ {
+ gimple *call = build_deferred_init (decl, init_type);
+ gimple_call_set_lhs (call, decl);
+ gimplify_seq_add_stmt (seq_p, call);
+ }
+ else
+ gcc_assert (0);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
/* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
and initialization explicit. */
@@ -1831,6 +2000,17 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
as they may contain a label address. */
walk_tree (&init, force_labels_r, NULL, NULL);
}
+ /* When there is no explicit initializer, if the user requested,
+ We should insert an artifical initializer for this automatic
+ variable for non vla variables. */
+ else if (flag_trivial_auto_var_init > AUTO_INIT_UNINITIALIZED
+ && !DECL_UNINITIALIZED (decl)
+ && !TREE_STATIC (decl)
+ && !is_vla)
+ gimple_add_init_for_auto_var (decl,
+ flag_trivial_auto_var_init,
+ flag_auto_init_approach,
+ seq_p);
}
return GS_ALL_DONE;
@@ -5015,6 +5195,17 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
/* If a single access to the target must be ensured and all elements
are zero, then it's optimal to clear whatever their number. */
cleared = true;
+ else if (flag_trivial_auto_var_init > AUTO_INIT_UNINITIALIZED
+ && !TREE_STATIC (object)
+ && type_has_padding (type))
+ /* If the user requests to initialize automatic variables with
+ paddings inside the type, we should initialize the paddings too.
+ C guarantees that brace-init with fewer initializers than members
+ aggregate will initialize the rest of the aggregate as-if it were
+ static initialization. In turn static initialization guarantees
+ that pad is initialized to zero bits.
+ So, it's better to clear the whole record under such situation. */
+ cleared = true;
else
cleared = false;
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index dd71731..a2e2075 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2963,6 +2963,30 @@ expand_UNIQUE (internal_fn, gcall *stmt)
emit_insn (pattern);
}
+/* Expand the IFN_DEFERRED_INIT function according to its second argument. */
+static void
+expand_DEFERRED_INIT (internal_fn, gcall *stmt)
+{
+ tree var = gimple_call_lhs (stmt);
+ tree init = NULL_TREE;
+ enum auto_init_type init_type
+ = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
+
+ switch (init_type)
+ {
+ default:
+ gcc_unreachable ();
+ case AUTO_INIT_PATTERN:
+ init = build_pattern_cst (TREE_TYPE (var));
+ expand_assignment (var, init, false);
+ break;
+ case AUTO_INIT_ZERO:
+ init = build_zero_cst (TREE_TYPE (var));
+ expand_assignment (var, init, false);
+ break;
+ }
+}
+
/* The size of an OpenACC compute dimension. */
static void
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index daeace7..7249ce7 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -356,6 +356,11 @@ DEF_INTERNAL_FN (VEC_CONVERT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (PHI, 0, NULL)
+/* A function to represent an artifical initialization to an uninitialized
+ automatic variable. The first argument is the variable itself, the
+ second argument is the initialization type. */
+DEF_INTERNAL_FN (DEFERRED_INIT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+
/* DIM_SIZE and DIM_POS return the size of a particular compute
dimension and the executing thread's position within that
dimension. DIM_POS is pure (and not const) so that it isn't
diff --git a/gcc/testsuite/c-c++-common/auto-init-1.c b/gcc/testsuite/c-c++-common/auto-init-1.c
new file mode 100644
index 0000000..a29b18e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-1.c
@@ -0,0 +1,39 @@
+/* Verify zero initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(temp2, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(temp3, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(temp4, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(temp5, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(temp6, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(temp7, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(temp8, 2\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-10.c b/gcc/testsuite/c-c++-common/auto-init-10.c
new file mode 100644
index 0000000..0955889
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-10.c
@@ -0,0 +1,17 @@
+/* Verify the variable attribute "uninitialized". */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+extern void bar (char, long long *) __attribute__ ((uninitialized)); /* { dg-warning "'uninitialized' attribute ignored" } */
+
+void foo()
+{
+ short temp1;
+ long long __attribute__ ((uninitialized)) temp2[10];
+
+ bar (temp1, temp2);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "temp2 = .DEFERRED_INIT \\(temp2, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-11.c b/gcc/testsuite/c-c++-common/auto-init-11.c
new file mode 100644
index 0000000..12d9ed6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-11.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+ int arr[n];
+ bar (arr[2]);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "__builtin_memset" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-12.c b/gcc/testsuite/c-c++-common/auto-init-12.c
new file mode 100644
index 0000000..189f650
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-12.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+ int arr[n];
+ bar (arr[2]);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "__builtin_memcpy" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-13.c b/gcc/testsuite/c-c++-common/auto-init-13.c
new file mode 100644
index 0000000..177659c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-13.c
@@ -0,0 +1,23 @@
+/* Verify the auto initialization of structure or union with a flexible array
+ member. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+struct a {
+ int b;
+ int array[];
+};
+union tar {
+ struct a bar;
+ char buf;
+};
+
+int foo()
+{
+ struct a d;
+ union tar var;
+ return d.b + var.bar.b;
+}
+
+/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(d, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(var, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-14.c b/gcc/testsuite/c-c++-common/auto-init-14.c
new file mode 100644
index 0000000..59d0503
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-14.c
@@ -0,0 +1,23 @@
+/* Verify the auto initialization of structure or union with a flexible array
+ member. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+struct a {
+ int b;
+ int array[];
+};
+union tar {
+ struct a bar;
+ char buf;
+};
+
+int foo()
+{
+ struct a d;
+ union tar var;
+ return d.b + var.bar.b;
+}
+
+/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(d, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(var, 2\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-2.c b/gcc/testsuite/c-c++-common/auto-init-2.c
new file mode 100644
index 0000000..07c2f38
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-2.c
@@ -0,0 +1,39 @@
+/* Verify pattern initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(temp2, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(temp3, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(temp4, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(temp5, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(temp6, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(temp7, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(temp8, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-3.c b/gcc/testsuite/c-c++-common/auto-init-3.c
new file mode 100644
index 0000000..c6b301d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-3.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(temp2, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(temp3, 2\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-4.c b/gcc/testsuite/c-c++-common/auto-init-4.c
new file mode 100644
index 0000000..db23469
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-4.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(temp2, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(temp3, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-5.c b/gcc/testsuite/c-c++-common/auto-init-5.c
new file mode 100644
index 0000000..596b066
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-5.c
@@ -0,0 +1,21 @@
+/* Verify zero initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(temp2, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(temp3, 2\\)" "gimple" } } */
+
diff --git a/gcc/testsuite/c-c++-common/auto-init-6.c b/gcc/testsuite/c-c++-common/auto-init-6.c
new file mode 100644
index 0000000..725d80a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-6.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(temp2, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(temp3, 1\\)" "gimple" } } */
+
diff --git a/gcc/testsuite/c-c++-common/auto-init-7.c b/gcc/testsuite/c-c++-common/auto-init-7.c
new file mode 100644
index 0000000..9fd2edc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-7.c
@@ -0,0 +1,35 @@
+/* Verify zero initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(temp2, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(temp3, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(temp4, 2\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-8.c b/gcc/testsuite/c-c++-common/auto-init-8.c
new file mode 100644
index 0000000..06dfc97
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-8.c
@@ -0,0 +1,35 @@
+/* Verify pattern initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(temp2, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(temp3, 1\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(temp4, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-9.c b/gcc/testsuite/c-c++-common/auto-init-9.c
new file mode 100644
index 0000000..32dd342
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-9.c
@@ -0,0 +1,17 @@
+/* Verify the variable attribute "uninitialized". */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+extern void bar (char, long long *) __attribute__ ((uninitialized)); /* { dg-warning "'uninitialized' attribute ignored" } */
+
+void foo()
+{
+ short temp1;
+ long long __attribute__ ((uninitialized)) temp2[10];
+
+ bar (temp1, temp2);
+ return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(temp1, 2\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "temp2 = .DEFERRED_INIT \\(temp2, 2\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-esra.c b/gcc/testsuite/c-c++-common/auto-init-esra.c
new file mode 100644
index 0000000..b204374
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-esra.c
@@ -0,0 +1,35 @@
+/* Verify the strength reduction adjustment for -ftrivial-auto-var-init. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftrivial-auto-var-init=zero -fauto-var-init-approach=D -fdump-tree-gimple -fdump-tree-esra" } */
+
+
+typedef double VECTOR[3];
+
+enum
+{
+ X = 0,
+ Y = 1,
+ Z = 2,
+ T = 3
+};
+
+void Assign_Vector(VECTOR d, VECTOR s)
+{
+ d[X] = s[X];
+ d[Y] = s[Y];
+ d[Z] = s[Z];
+}
+
+void VCross(VECTOR a, const VECTOR b, const VECTOR c)
+{
+ VECTOR tmp;
+
+ tmp[X] = b[Y] * c[Z] - b[Z] * c[Y];
+ tmp[Y] = b[Z] * c[X] - b[X] * c[Z];
+ tmp[Z] = b[X] * c[Y] - b[Y] * c[X];
+
+ Assign_Vector(a, tmp);
+}
+
+/* { dg-final { scan-tree-dump-times "tmp = .DEFERRED_INIT \\(tmp, 2\\)" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times ".DEFERRED_INIT \\(tmp" 3 "esra" } } */
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C
new file mode 100644
index 0000000..33c1744
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int get_time ();
+
+class A
+{
+public:
+ A ();
+ ~A () {
+ if (I) delete I;
+ }
+
+private:
+ int* I;
+};
+
+bool get_url (A *);
+
+class M {
+
+ public:
+__attribute__ ((always_inline)) int GetC (int *c) {
+
+ A details_str;
+ if (!get_url (&details_str))
+ {
+ incr ();
+ return 1;
+ }
+
+ *c = get_time ();
+ return -1;
+ }
+
+ void do_sth();
+ void do_sth2();
+
+ void P (int64 t)
+ {
+ int cc; /* { dg-bogus "uninitialized" "uninitialized variable warning" } */
+ if (GetC (&cc) >= 0 )
+ return;
+
+ if (t && cc <= 0 ) /* { dg-bogus "uninitialized" "uninitialized variable warning" } */
+ {
+ this->do_sth();
+ return;
+ }
+
+ do_sth2();
+ }
+};
+
+M* m;
+void foo(int x)
+{
+ m = new M;
+ m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_b.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_b.C
new file mode 100644
index 0000000..6b6bdae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_b.C
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int get_time ();
+
+class A
+{
+public:
+ A ();
+ ~A () {
+ if (I) delete I;
+ }
+
+private:
+ int* I;
+};
+
+bool get_url (A *);
+
+class M {
+
+ public:
+__attribute__ ((always_inline)) int GetC (int *c) {
+
+ A details_str;
+ if (!get_url (&details_str))
+ {
+ incr ();
+ return 1;
+ }
+
+ *c = get_time ();
+ return -1;
+ }
+
+ void do_sth();
+ void do_sth2();
+
+ void P (int64 t)
+ {
+ int cc; /* { dg-message "note: 'cc' was declared here" } */
+ if (GetC (&cc) <= 0 ) /* return flag checked wrongly */
+ return;
+
+ if (t && cc <= 0 ) /* { dg-warning "uninitialized" "uninitialized variable warning" } */
+ {
+ this->do_sth();
+ return;
+ }
+
+ do_sth2();
+ }
+};
+
+M* m;
+void foo(int x)
+{
+ m = new M;
+ m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C
new file mode 100644
index 0000000..fc18cb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C
@@ -0,0 +1,62 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int get_time ();
+
+class A
+{
+public:
+ A ();
+ ~A () {
+ if (I) delete I;
+ }
+
+private:
+ int* I;
+};
+
+bool get_url (A *);
+
+class M {
+
+ public:
+__attribute__ ((always_inline)) bool GetC (int *c) {
+
+ A details_str;
+ if (get_url (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ return false;
+ }
+
+ void do_sth();
+ void do_sth2();
+
+ void P (int64 t)
+ {
+ int cc;
+ if (!GetC (&cc)) /* return flag checked properly */
+ return;
+
+ if (cc <= 0) /* { dg-bogus "uninitialized" "uninitialized variable warning" } */
+ {
+ this->do_sth();
+ return;
+ }
+
+ do_sth2();
+ }
+};
+
+M* m;
+void foo(int x)
+{
+ m = new M;
+ m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_b.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_b.C
new file mode 100644
index 0000000..e85a36f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_b.C
@@ -0,0 +1,62 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int get_time ();
+
+class A
+{
+public:
+ A ();
+ ~A () {
+ if (I) delete I;
+ }
+
+private:
+ int* I;
+};
+
+bool get_url (A *);
+
+class M {
+
+ public:
+__attribute__ ((always_inline)) bool GetC (int *c) {
+
+ A details_str;
+ if (get_url (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ return false;
+ }
+
+ void do_sth();
+ void do_sth2();
+
+ void P (int64 t)
+ {
+ int cc; /* { dg-message "note: 'cc' was declared here" } */
+ if (GetC (&cc)) /* return flag checked wrongly */
+ return;
+
+ if (cc <= 0) /* { dg-warning "uninitialized" "uninitialized variable warning" } */
+ {
+ this->do_sth();
+ return;
+ }
+
+ do_sth2();
+ }
+};
+
+M* m;
+void foo(int x)
+{
+ m = new M;
+ m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C
new file mode 100644
index 0000000..09ed692
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C
@@ -0,0 +1,77 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+/* Multiple initialization paths. */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int get_time ();
+
+class A
+{
+public:
+ A ();
+ ~A () {
+ if (I) delete I;
+ }
+
+private:
+ int* I;
+};
+
+bool get_url (A *);
+bool get_url2 (A *);
+
+class M {
+
+ public:
+ __attribute__ ((always_inline))
+ bool GetC (int *c) {
+
+ A details_str;
+ /* Intialization path 1 */
+ if (get_url (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ /* insert dtor calls (inlined) into following return paths */
+ A tmp_str;
+
+ /* Intializtion path 2 */
+ if (get_url2 (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ return false;
+ }
+
+ void do_sth();
+ void do_sth2();
+
+ void P (int64 t)
+ {
+ int cc;
+ if (!GetC (&cc)) /* return flag checked properly */
+ return;
+
+ if (cc <= 0) /* { dg-bogus "uninitialized" "uninitialized variable warning" } */
+ {
+ this->do_sth();
+ return;
+ }
+
+ do_sth2();
+ }
+};
+
+M* m;
+void test(int x)
+{
+ m = new M;
+ m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_b.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_b.C
new file mode 100644
index 0000000..8e7b854
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_b.C
@@ -0,0 +1,87 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+/* Multiple initialization paths. */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int get_time ();
+
+class A
+{
+public:
+ A ();
+ ~A () {
+ if (I) delete I;
+ }
+
+private:
+ int* I;
+};
+
+bool get_url (A *);
+bool get_url2 (A *);
+bool get_url3 (A *);
+
+class M {
+
+ public:
+ __attribute__ ((always_inline))
+ bool GetC (int *c) {
+
+ A details_str;
+
+ /* Initialization path 1 */
+ if (get_url (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ /* Destructor call before return*/
+ A tmp_str;
+
+ /* Initialization path 2 */
+ if (get_url2 (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ /* Fail to initialize in this path but
+ still returns true */
+ if (get_url2 (&details_str))
+ {
+ /* Fail to initialize *c */
+ return true;
+ }
+
+ return false;
+ }
+
+ void do_sth();
+ void do_sth2();
+
+ void P (int64 t)
+ {
+ int cc;
+ if (!GetC (&cc))
+ return;
+
+ if (cc <= 0) /* { dg-warning "uninitialized" "uninitialized variable warning" } */
+ {
+ this->do_sth();
+ return;
+ }
+
+ do_sth2();
+ }
+};
+
+M* m;
+void test(int x)
+{
+ m = new M;
+ m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C
new file mode 100644
index 0000000..c48770a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -Og -ftrivial-auto-var-init=zero" } */
+
+int pop ();
+int pop_first_bucket;
+
+int my_pop ()
+{
+ int out; // { dg-bogus "uninitialized" "uninitialized variable warning" }
+
+ while (pop_first_bucket)
+ if (pop_first_bucket && (out = pop()))
+ return out;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_a.cc b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_a.cc
new file mode 100644
index 0000000..629677a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_a.cc
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+extern int bar();
+int foo(void)
+{
+ for (;;) {
+ int err = ({int _err; /* { dg-bogus "uninitialized" "false warning" } */
+ for (int i = 0; i < 16; ++i) {
+ _err = 17;
+ _err = bar();
+ }
+ _err; /* { dg-bogus "uninitialized" "false warning" } */
+ });
+
+ if (err == 0) return 17;
+ }
+
+ return 18;
+}
+
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_b.cc b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_b.cc
new file mode 100644
index 0000000..04ab364
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_b.cc
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+extern int bar();
+int foo(int n)
+{
+ for (;;) {
+ int err = ({int _err;
+ for (int i = 0; i < n; ++i) {
+ _err = 17;
+ _err = bar();
+ }
+ _err;
+ }); /* { dg-warning "uninitialized" "warn on _err" } */
+
+ if (err == 0) return 17;
+ }
+
+ return 18;
+}
+
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_c.cc b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_c.cc
new file mode 100644
index 0000000..82a1846
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_c.cc
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+extern int bar();
+int foo(int n, int m)
+{
+ for (;;) {
+ int err = ({int _err;
+ for (int i = 0; i < 16; ++i) {
+ if (m+i > n)
+ break;
+ _err = 17;
+ _err = bar();
+ }
+ _err;
+ });
+
+ if (err == 0) return 17; }); /* { dg-warning "uninitialized" "warn on _err" } */
+ }
+
+ return 18;
+}
+
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop_1.cc b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop_1.cc
new file mode 100644
index 0000000..629677a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop_1.cc
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+extern int bar();
+int foo(void)
+{
+ for (;;) {
+ int err = ({int _err; /* { dg-bogus "uninitialized" "false warning" } */
+ for (int i = 0; i < 16; ++i) {
+ _err = 17;
+ _err = bar();
+ }
+ _err; /* { dg-bogus "uninitialized" "false warning" } */
+ });
+
+ if (err == 0) return 17;
+ }
+
+ return 18;
+}
+
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-1.c b/gcc/testsuite/gcc.dg/auto-init-uninit-1.c
new file mode 100644
index 0000000..cb0e7cc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-1.c
@@ -0,0 +1,30 @@
+/* Spurious uninitialized variable warnings, case 1.
+ Taken from cppfiles.c (merge_include_chains) */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+struct list
+{
+ struct list *next;
+ int id;
+};
+
+extern void free (void *);
+
+void remove_dupes (struct list *el)
+{
+ struct list *p, *q, *r; /* { dg-bogus "r" "uninitialized variable warning" } */
+
+ for (p = el; p; p = p->next)
+ {
+ for (q = el; q != p; q = q->next)
+ if (q->id == p->id)
+ {
+ r->next = p->next;
+ free (p);
+ p = r;
+ break;
+ }
+ r = p;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-11.c b/gcc/testsuite/gcc.dg/auto-init-uninit-11.c
new file mode 100644
index 0000000..559e2d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-11.c
@@ -0,0 +1,42 @@
+/* Positive test for uninitialized variables. */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+int sink;
+
+void f1(int parm) /* { dg-bogus "uninitialized" "parameter" } */
+{
+ sink = parm; /* { dg-bogus "uninitialized" "parameter" } */
+}
+
+void f2(void)
+{
+ int x;
+ sink = x; /* { dg-warning "is used" "unconditional" } */
+}
+
+void f3(int p)
+{
+ int x;
+ if (p)
+ x = p;
+ sink = x; /* { dg-warning "may be used" "conditional" } */
+}
+
+void f4(int p)
+{
+ int x; /* { dg-bogus "uninitialized" "easy if" } */
+ if (p)
+ x = 1;
+ else
+ x = 2;
+ sink = x;
+}
+
+void f5(void)
+{
+ int x, i; /* { dg-bogus "uninitialized" "easy loop" } */
+ for (i = 0; i < 10; ++i)
+ x = 1;
+ sink = x;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-12.c b/gcc/testsuite/gcc.dg/auto-init-uninit-12.c
new file mode 100644
index 0000000..acff725
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-12.c
@@ -0,0 +1,12 @@
+/* PR 23497 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+typedef _Complex float C;
+C foo()
+{
+ C f;
+ __real__ f = 0;
+ __imag__ f = 0;
+ return f;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-13.c b/gcc/testsuite/gcc.dg/auto-init-uninit-13.c
new file mode 100644
index 0000000..87dd8b5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-13.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+typedef _Complex float C;
+C foo()
+{
+ C f;
+ __imag__ f = 0;
+ return f; /* { dg-warning "is used" "unconditional" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-14.c b/gcc/testsuite/gcc.dg/auto-init-uninit-14.c
new file mode 100644
index 0000000..592052a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-14.c
@@ -0,0 +1,20 @@
+/* PR 24931 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+struct p {
+ short x, y;
+};
+
+struct s {
+ int i;
+ struct p p;
+};
+
+struct s f()
+{
+ struct s s;
+ s.p = (struct p){};
+ s.i = (s.p.x || s.p.y);
+ return s;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-15.c b/gcc/testsuite/gcc.dg/auto-init-uninit-15.c
new file mode 100644
index 0000000..121f0cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-15.c
@@ -0,0 +1,26 @@
+/* PR tree-optimization/17506
+ We issue an uninitialized variable warning at a wrong location at
+ line 11, which is very confusing. Make sure we print out a note to
+ make it less confusing. (not xfailed alternative)
+ But it is of course ok if we warn in bar about uninitialized use
+ of j. (not xfailed alternative) */
+/* { dg-do compile } */
+/* { dg-options "-O1 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+inline int
+foo (int i)
+{
+ if (i) /* { dg-warning "used uninitialized" } */
+ return 1;
+ return 0;
+}
+
+void baz (void);
+
+void
+bar (void)
+{
+ int j; /* { dg-message "note: 'j' was declared here" "" } */
+ for (; foo (j); ++j) /* { dg-warning "'j' is used uninitialized" "" { xfail *-*-* } } */
+ baz ();
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-16.c b/gcc/testsuite/gcc.dg/auto-init-uninit-16.c
new file mode 100644
index 0000000..0e4f336
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-16.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+int foo, bar;
+
+static
+void decode_reloc(int reloc, int *is_alt)
+{
+ if (reloc >= 20)
+ *is_alt = 1;
+ else if (reloc >= 10)
+ *is_alt = 0;
+}
+
+void testfunc()
+{
+ int alt_reloc;
+
+ decode_reloc(foo, &alt_reloc);
+
+ if (alt_reloc) /* { dg-warning "may be used uninitialized" } */
+ bar = 42;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-17.c b/gcc/testsuite/gcc.dg/auto-init-uninit-17.c
new file mode 100644
index 0000000..9eec944
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-17.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+typedef _Complex float C;
+C foo(int cond)
+{
+ C f;
+ __imag__ f = 0;
+ if (cond)
+ {
+ __real__ f = 1;
+ return f;
+ }
+ return f; /* { dg-warning "may be used" "unconditional" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-18.c b/gcc/testsuite/gcc.dg/auto-init-uninit-18.c
new file mode 100644
index 0000000..4922848
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-18.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+char *foo(int bar, char *baz)
+{
+ char *tmp;
+
+ if (bar & 3)
+ tmp = baz;
+
+ switch (bar) {
+ case 1:
+ tmp[5] = 7; /* { dg-bogus "may be used uninitialized" } */
+ break;
+ case 2:
+ tmp[11] = 15; /* { dg-bogus "may be used uninitialized" } */
+ break;
+ default:
+ tmp = 0;
+ break;
+ }
+
+ return tmp; /* { dg-bogus "may be used uninitialized" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-19.c b/gcc/testsuite/gcc.dg/auto-init-uninit-19.c
new file mode 100644
index 0000000..38d27e4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-19.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+/* { dg-additional-options "-finline-small-functions" { target avr-*-* } } */
+
+int a, l, m;
+float *b;
+float c, d, e, g, h;
+unsigned char i, k;
+void
+fn1 (int p1, float *f1, float *f2, float *f3, unsigned char *c1, float *f4,
+ unsigned char *c2, float *p10)
+{
+ if (p1 & 8)
+ b[3] = p10[a];
+ /* { dg-warning "may be used uninitialized" "" { target { { nonpic || pie_enabled } || { hppa*64*-*-* *-*-darwin* } } } .-1 } */
+}
+
+void
+fn2 ()
+{
+ float *n;
+ if (l & 6)
+ n = &c + m;
+ fn1 (l, &d, &e, &g, &i, &h, &k, n);
+ /* { dg-warning "may be used uninitialized" "" { target { ! { { nonpic || pie_enabled } || { hppa*64*-*-* *-*-darwin* } } } } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-2.c b/gcc/testsuite/gcc.dg/auto-init-uninit-2.c
new file mode 100644
index 0000000..da03bf8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-2.c
@@ -0,0 +1,52 @@
+/* Spurious uninitialized variable warnings, case 2.
+ Taken from cpphash.c (macroexpand) */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+struct definition
+{
+ int nargs;
+ int rest_args;
+};
+
+struct cpp_reader;
+
+enum cpp_token
+{
+ CPP_EOF, CPP_POP, CPP_COMMA, CPP_RPAREN
+};
+
+extern enum cpp_token macarg (struct cpp_reader *, int);
+
+void
+macroexpand (struct cpp_reader *pfile, struct definition *defn)
+{
+ int nargs = defn->nargs;
+
+ if (nargs >= 0)
+ {
+ enum cpp_token token; /* { dg-bogus "token" "uninitialized variable warning" } */
+ int i, rest_args;
+ i = 0;
+ rest_args = 0;
+ do
+ {
+ if (rest_args)
+ continue;
+ if (i < nargs || (nargs == 0 && i == 0))
+ {
+ /* if we are working on last arg which absorbs rest of args... */
+ if (i == nargs - 1 && defn->rest_args)
+ rest_args = 1;
+ token = macarg (pfile, rest_args);
+ }
+ else
+ token = macarg (pfile, 0);
+ if (token == CPP_EOF || token == CPP_POP)
+ return;
+
+ i++;
+ }
+ while (token == CPP_COMMA);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-20.c b/gcc/testsuite/gcc.dg/auto-init-uninit-20.c
new file mode 100644
index 0000000..f533ce9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-20.c
@@ -0,0 +1,18 @@
+/* Spurious uninitialized variable warnings, from gdb */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+struct os { struct o *o; };
+struct o { struct o *next; struct os *se; };
+void f(struct o *o){
+ struct os *s;
+ if(o) s = o->se;
+ while(o && s == o->se){
+ s++; // here `o' is non-zero and thus s is initialized
+ s == o->se // `?' is essential, `if' does not trigger the warning
+ ? (o = o->next, o ? s = o->se : 0)
+ : 0;
+ }
+}
+
+
+
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-21.c b/gcc/testsuite/gcc.dg/auto-init-uninit-21.c
new file mode 100644
index 0000000..6044eab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-21.c
@@ -0,0 +1,33 @@
+/* PR69537, spurious warning because of a missed optimization. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-short-enums -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+enum clnt_stat {
+ RPC_SUCCESS=0,
+ RPC_CANTENCODEARGS=1,
+};
+
+int do_ypcall_tr ();
+
+static int
+yp_master (char **outname)
+{
+ // Replacing enum clnt_stat with int avoids the warning.
+ enum clnt_stat result;
+ result = do_ypcall_tr ();
+ if (result != 0)
+ return result;
+ *outname = __builtin_strdup ("foo");
+ return 0;
+}
+
+int
+yp_update (void)
+{
+ char *master;
+ int r;
+ if ((r = yp_master (&master)) != 0)
+ return r;
+ __builtin_free (master); /* { dg-bogus "uninitialized" } */
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-22.c b/gcc/testsuite/gcc.dg/auto-init-uninit-22.c
new file mode 100644
index 0000000..0200d73
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-22.c
@@ -0,0 +1,69 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wuninitialized --param vect-max-version-for-alias-checks=20 -ftrivial-auto-var-init=zero" } */
+
+#include <stdint.h>
+
+#define A1 2896 /* (1/sqrt(2))<<12 */
+#define A2 2217
+#define A3 3784
+#define A4 -5352
+
+#define IDCT_TRANSFORM(dest,s0,s1,s2,s3,s4,s5,s6,s7,d0,d1,d2,d3,d4,d5,d6,d7,munge,src) {\
+ const int a0 = (src)[s0] + (src)[s4]; \
+ const int a1 = (src)[s0] - (src)[s4]; \
+ const int a2 = (src)[s2] + (src)[s6]; \
+ const int a3 = (A1*((src)[s2] - (src)[s6])) >> 11; \
+ const int a4 = (src)[s5] + (src)[s3]; \
+ const int a5 = (src)[s5] - (src)[s3]; \
+ const int a6 = (src)[s1] + (src)[s7]; \
+ const int a7 = (src)[s1] - (src)[s7]; \
+ const int b0 = a4 + a6; \
+ const int b1 = (A3*(a5 + a7)) >> 11; \
+ const int b2 = ((A4*a5) >> 11) - b0 + b1; \
+ const int b3 = (A1*(a6 - a4) >> 11) - b2; \
+ const int b4 = ((A2*a7) >> 11) + b3 - b1; \
+ (dest)[d0] = munge(a0+a2 +b0); \
+ (dest)[d1] = munge(a1+a3-a2+b2); \
+ (dest)[d2] = munge(a1-a3+a2+b3); \
+ (dest)[d3] = munge(a0-a2 -b4); \
+ (dest)[d4] = munge(a0-a2 +b4); \
+ (dest)[d5] = munge(a1-a3+a2-b3); \
+ (dest)[d6] = munge(a1+a3-a2-b2); \
+ (dest)[d7] = munge(a0+a2 -b0); \
+}
+
+#define MUNGE_NONE(x) (x)
+#define IDCT_COL(dest,src) IDCT_TRANSFORM(dest,0,8,16,24,32,40,48,56,0,8,16,24,32,40,48,56,MUNGE_NONE,src)
+
+#define MUNGE_ROW(x) (((x) + 0x7F)>>8)
+#define IDCT_ROW(dest,src) IDCT_TRANSFORM(dest,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,MUNGE_ROW,src)
+
+static inline void bink_idct_col(int *dest, const int32_t *src)
+{
+ if ((src[8]|src[16]|src[24]|src[32]|src[40]|src[48]|src[56])==0) {
+ dest[0] =
+ dest[8] =
+ dest[16] =
+ dest[24] =
+ dest[32] =
+ dest[40] =
+ dest[48] =
+ dest[56] = src[0];
+ } else {
+ IDCT_COL(dest, src);
+ }
+}
+
+int bink_idct_put_c(uint8_t *dest, int linesize, int32_t *block)
+{
+ int i;
+ int temp[64];
+ for (i = 0; i < 8; i++)
+ bink_idct_col(&temp[i], &block[i]);
+ for (i = 0; i < 8; i++) {
+ IDCT_ROW( (&dest[i*linesize]), (&temp[8*i]) );
+ }
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-23.c b/gcc/testsuite/gcc.dg/auto-init-uninit-23.c
new file mode 100644
index 0000000..7dce8d0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-23.c
@@ -0,0 +1,27 @@
+/* PR tree-optimization/78455 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+int ij;
+
+void
+ql (void)
+{
+ int m5 = 0;
+
+ for (;;)
+ {
+ if (0)
+ for (;;)
+ {
+ int *go;
+ int *t4 = go; /* { dg-warning "is used uninitialized" } */
+
+ l1:
+ *t4 = (*t4 != 0) ? 0 : 2;
+ }
+
+ if (ij != 0)
+ goto l1;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-24.c b/gcc/testsuite/gcc.dg/auto-init-uninit-24.c
new file mode 100644
index 0000000..1f6740c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-24.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wmaybe-uninitialized -ftrivial-auto-var-init=zero" } */
+
+int foo (int x)
+{
+ int y;
+ if (x)
+ return *(&y + 1); /* { dg-bogus "may be used uninitialized" } */
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-25.c b/gcc/testsuite/gcc.dg/auto-init-uninit-25.c
new file mode 100644
index 0000000..f36d95f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-25.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wmaybe-uninitialized -ftrivial-auto-var-init=zero" } */
+
+extern unsigned bar (void);
+extern void quux (void);
+
+unsigned foo (unsigned v)
+{
+ unsigned u;
+ if (v != 1)
+ u = bar ();
+
+ // Prevent the "dom" pass from changing the CFG layout based on the inference
+ // 'if (v != 1) is false then (v != 2) is true'. (Now it would have to
+ // duplicate the loop in order to do so, which is deemed expensive.)
+ for (int i = 0; i < 10; i++)
+ quux ();
+
+ if (v != 2)
+ return u; /* { dg-warning "may be used uninitialized" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-26.c b/gcc/testsuite/gcc.dg/auto-init-uninit-26.c
new file mode 100644
index 0000000..ae97ecf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-26.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wmaybe-uninitialized -ftrivial-auto-var-init=zero" } */
+
+extern unsigned bar (void);
+extern void quux (void);
+
+unsigned foo (unsigned v)
+{
+ unsigned u;
+ if (v != 100)
+ u = bar ();
+
+ // Prevent the "dom" pass from changing the CFG layout based on the inference
+ // 'if (v != 100) is false then (v < 105) is true'. (Now it would have to
+ // duplicate the loop in order to do so, which is deemed expensive.)
+ for (int i = 0; i < 10; i++)
+ quux ();
+
+ if (v < 105) /* v == 100 falls into this range. */
+ return u; /* { dg-warning "may be used uninitialized" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-3.c b/gcc/testsuite/gcc.dg/auto-init-uninit-3.c
new file mode 100644
index 0000000..7ff2285
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-3.c
@@ -0,0 +1,33 @@
+/* Spurious uninit variable warnings, case 3.
+ Inspired by cppexp.c (parse_charconst) */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+extern void error (char *);
+
+int
+parse_charconst (const char *start, const char *end)
+{
+ int c; /* { dg-bogus "c" "uninitialized variable warning" } */
+ int nchars, retval;
+
+ nchars = 0;
+ retval = 0;
+ while (start < end)
+ {
+ c = *start++;
+ if (c == '\'')
+ break;
+ nchars++;
+ retval += c;
+ retval <<= 8;
+ }
+
+ if (nchars == 0)
+ return 0;
+
+ if (c != '\'')
+ error ("malformed character constant");
+
+ return retval;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-34.c b/gcc/testsuite/gcc.dg/auto-init-uninit-34.c
new file mode 100644
index 0000000..98fc366
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-34.c
@@ -0,0 +1,58 @@
+/* PR middle-end/10138 - warn for uninitialized arrays passed as const*
+ arguments
+ Verify that passing pointers to uninitialized objects to arguments
+ to functions declared with attribute access is diagnosed where expected.
+ { dg-do compile }
+ { dg-options "-O -Wall -ftrivial-auto-var-init=zero" } */
+
+#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__)))
+
+RW (1) RW (3) void
+f4pi (int*, int*, int*, int*); // { dg-message "in a call to 'f4pi' declared with attribute 'access \\\(read_write, \[13\]\\\)'" }
+
+
+void nowarn_scalar (void)
+{
+ int i1 = 0, i2, i3 = 1, i4;
+ f4pi (&i1, &i2, &i3, &i4);
+}
+
+void warn_scalar_1 (void)
+{
+ int i1; // { dg-message "declared here" }
+ int i2, i3 = 1, i4;
+
+ f4pi (&i1, &i2, &i3, &i4); // { dg-warning "'i1' may be used uninitialized" }
+}
+
+void warn_scalar_2 (void)
+{
+ int j1 = 0, j2, j4;
+ int j3;
+
+ f4pi (&j1, &j2, &j3, &j4); // { dg-warning "'j3' may be used uninitialized" }
+}
+
+
+void nowarn_array_init (void)
+{
+ int a1[4] = { 0 }, a2[5], a3[6] = { 0 }, a4[7];
+
+ f4pi (a1, a2, a3, a4);
+}
+
+void warn_array_1 (void)
+{
+ int a1[4]; // { dg-message "'a1' declared here" }
+ int a2[5], a3[6] = { 0 }, a4[7];
+
+ f4pi (a1, a2, a3, a4); // { dg-warning "'a1' may be used uninitialized" }
+}
+
+void warn_array_2 (void)
+{
+ int a1[4] = { 0 }, a2[5], a4[7];
+ int a3[6]; // { dg-message "'a3' declared here" }
+
+ f4pi (a1, a2, a3, a4); // { dg-warning "'a3' may be used uninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-36.c b/gcc/testsuite/gcc.dg/auto-init-uninit-36.c
new file mode 100644
index 0000000..64377d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-36.c
@@ -0,0 +1,238 @@
+/* PR middle-end/10138 - warn for uninitialized arrays passed as const*
+ arguments
+ Verify that passing pointers to uninitialized objects to const
+ arguments to built-ins is diagnosed where expected.
+ { dg-do compile }
+ { dg-options "-O -Wall -ftrivial-auto-var-init=zero" }
+ { dg-require-effective-target alloca } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* alloca (size_t);
+void* malloc (size_t);
+void* realloc (void*, size_t);
+
+void* memcpy (void*, const void*, size_t);
+char* strcpy (char*, const char*);
+size_t strlen (const char*);
+
+void sink (void*);
+
+void nowarn_array_memcpy (void *d, unsigned n)
+{
+ int a[2];
+ /* Diagnose this? */
+ memcpy (d, a, n /* Non-constant to avoid folding into MEM_REF. */);
+}
+
+void nowarn_array_plus_cst_memcpy (void *d, unsigned n)
+{
+ int a[3];
+ /* Diagnose this? */
+ memcpy (d, a + 1, n);
+}
+
+void nowarn_array_plus_var_memcpy (void *d, unsigned n, int i)
+{
+ int a[4];
+ /* Diagnose this? */
+ memcpy (d, a + i, n);
+}
+
+void nowarn_array_assign_memcpy (char *d, unsigned n)
+{
+ int a[3];
+ a[1] = 3;
+ memcpy (d, a, n);
+}
+
+void nowarn_array_init_memcpy (char *d, unsigned n)
+{
+ int a[4] = { 0 };
+ memcpy (d, a, n);
+}
+
+void nowarn_array_compound_memcpy (void *d, unsigned n)
+{
+ memcpy (d, (int[2]){ 0 }, n);
+}
+
+void nowarn_struct_assign_memcpy (void *d, unsigned n)
+{
+ struct S { int a, b, c, d; } s;
+ s.b = 1;
+ s.d = 2;
+ memcpy (d, &s, n);
+}
+
+
+void nowarn_array_init_strcpy (char *d[], unsigned n)
+{
+ char a[8] = "012";
+
+ strcpy (d[0], a);
+ strcpy (d[1], a + 1);
+ strcpy (d[1], a + 2);
+ strcpy (d[1], a + 3);
+ strcpy (d[1], a + 4);
+ strcpy (d[1], a + 5);
+ strcpy (d[1], a + 6);
+ strcpy (d[1], a + 7);
+}
+
+
+void nowarn_array_assign_strcpy (char *d[], unsigned n)
+{
+ char a[8];
+ a[0] = '0';
+ a[1] = '1';
+ a[2] = '2';
+ a[3] = '\0';
+
+ strcpy (d[0], a);
+ strcpy (d[1], a + 1);
+ strcpy (d[1], a + 2);
+ strcpy (d[1], a + 3);
+}
+
+void warn_array_plus_cst_strcpy (char *d, unsigned n)
+{
+ char a[8];
+ a[0] = '1';
+ a[1] = '2';
+ a[2] = '3';
+ a[3] = '\0';
+
+ strcpy (d, a + 4); // { dg-warning "\\\[-Wuninitialized" }
+ strcpy (d, a + 5); // { dg-warning "\\\[-Wuninitialized" }
+ strcpy (d, a + 6); // { dg-warning "\\\[-Wuninitialized" }
+ strcpy (d, a + 7); // { dg-warning "\\\[-Wuninitialized" }
+}
+
+void nowarn_array_plus_var_strcpy (char *d, int i)
+{
+ char a[8];
+ a[0] = '1';
+ a[1] = '2';
+ a[2] = '3';
+ a[3] = '\0';
+
+ strcpy (d, a + i);
+}
+
+
+size_t nowarn_array_assign_strlen (const char *s)
+{
+ char a[8];
+ a[0] = s[0];
+ a[1] = s[1];
+ a[2] = s[2];
+ a[3] = s[3];
+
+ size_t n = 0;
+
+ n += strlen (a);
+ n += strlen (a + 1);
+ n += strlen (a + 2);
+ n += strlen (a + 3);
+ return n;
+}
+
+size_t warn_array_plus_cst_strlen (const char *s)
+{
+ char a[8];
+ a[0] = s[0];
+ a[1] = s[1];
+ a[2] = s[2];
+ a[3] = s[3];
+
+ return strlen (a + 4); // { dg-warning "\\\[-Wuninitialized" }
+}
+
+size_t nowarn_array_plus_var_strlen (const char *s, int i)
+{
+ char a[8];
+ a[0] = s[0];
+ a[1] = s[1];
+ a[2] = s[2];
+ a[3] = s[3];
+
+ return strlen (a + i);
+}
+
+
+size_t nowarn_alloca_assign_strlen (int i)
+{
+ char *p = (char*)alloca (8);
+ p[i] = '\0';
+ return strlen (p);
+}
+
+size_t nowarn_alloca_escape_strlen (int i)
+{
+ char *p = (char*)alloca (8);
+ sink (p);
+ return strlen (p);
+}
+
+size_t warn_alloca_strlen (void)
+{
+ char *p = (char*)alloca (8);
+ return strlen (p); // { dg-warning "\\\[-Wuninitialized" }
+}
+
+
+size_t nowarn_malloc_assign_strlen (int i)
+{
+ char *p = (char*)malloc (8);
+ p[i] = '\0';
+ return strlen (p);
+}
+
+size_t nowarn_malloc_escape_strlen (int i)
+{
+ char *p = (char*)malloc (8);
+ sink (p);
+ return strlen (p);
+}
+
+size_t warn_malloc_strlen (void)
+{
+ char *p = (char*)malloc (8);
+ return strlen (p); // { dg-warning "\\\[-Wuninitialized" }
+}
+
+
+size_t nowarn_realloc_strlen (void *p)
+{
+ char *q = (char*)realloc (p, 8);
+ return strlen (q);
+}
+
+
+size_t nowarn_vla_assign_strlen (int n, int i)
+{
+ char vla[n];
+ vla[i] = '\0';
+ return strlen (vla);
+}
+
+size_t nowarn_vla_strcpy_strlen (int n, const char *s, int i)
+{
+ char vla[n];
+ strcpy (vla, s);
+ return strlen (vla + i);
+}
+
+size_t nowarn_vla_escape_strlen (int n, int i)
+{
+ char vla[n];
+ sink (vla);
+ return strlen (vla);
+}
+
+size_t warn_vla_strlen (unsigned n)
+{
+ char vla[n];
+ return strlen (vla); // { dg-warning "\\\[-Wuninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-37.c b/gcc/testsuite/gcc.dg/auto-init-uninit-37.c
new file mode 100644
index 0000000..da3c9db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-37.c
@@ -0,0 +1,154 @@
+/* PR middle-end/10138 - warn for uninitialized arrays passed as const arguments
+ Verify that -Wuninitialized and -Wmaybe-uninitialized trigger (or don't)
+ when passing uninitialized variables by reference to functions declared
+ with or without attribute access and with (or without) const qualified
+ arguments of array, VLA, or pointer types.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -ftrack-macro-expansion=0 -ftrivial-auto-var-init=zero" } */
+
+#define NONE /* none */
+#define RO(...) __attribute__ ((access (read_only, __VA_ARGS__)))
+#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__)))
+#define WO(...) __attribute__ ((access (write_only, __VA_ARGS__)))
+#define X(...) __attribute__ ((access (none, __VA_ARGS__)))
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define UNIQ(pfx) CAT (pfx, __LINE__)
+
+extern void sink (void*);
+
+
+#define T1(attr, name, type) \
+ void UNIQ (CAT (test_, name))(void) { \
+ extern attr void UNIQ (name)(type); \
+ int x; \
+ UNIQ (name)(&x); \
+ sink (&x); \
+ }
+
+#define T2(attr, name, types) \
+ void UNIQ (CAT (test_, name))(void) { \
+ extern attr void UNIQ (name)(types); \
+ int x; \
+ UNIQ (name)(1, &x); \
+ sink (&x); \
+ }
+
+
+typedef int IA_[];
+typedef const int CIA_[];
+
+T1 (NONE, fia_, IA_);
+T1 (NONE, fcia_, CIA_); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froia_, IA_); // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwia_, IA_); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoia_, IA_);
+T1 (X (1), fxia_, IA_);
+
+
+typedef int IA1[1];
+typedef const int CIA1[1];
+
+T1 (NONE, fia1, IA1);
+T1 (NONE, fcia1, CIA1); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froia1, IA1); // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwia1, IA1); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoia1, IA1);
+T1 (X (1), fxia1, IA1);
+
+
+#define IARS1 int[restrict static 1]
+#define CIARS1 const int[restrict static 1]
+
+T1 (NONE, fiars1, IARS1);
+T1 (NONE, fciars1, CIARS1);// { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froiars1, IARS1); // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwiars1, IARS1); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoiars1, IARS1);
+T1 (X (1), fxiars1, IARS1);
+
+
+#define IAS1 int[static 1]
+#define CIAS1 const int[static 1]
+
+T1 (NONE, fias1, IAS1);
+T1 (NONE, fcias1, CIAS1); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froias1, IAS1); // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwias1, IAS1); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoias1, IAS1);
+T1 (X (1), fxias1, IAS1);
+
+
+#define IAX int[*]
+#define CIAX const int[*]
+
+T1 (NONE, fiax, IAX);
+T1 (NONE, fciax, CIAX); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froiax, IAX); // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwiax, IAX); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoiax, IAX);
+T1 (X (1), fxiax, IAX);
+
+
+#define IAN int n, int[n]
+#define CIAN int n, const int[n]
+
+T2 (NONE, fian, IAN);
+T2 (NONE, fcian, CIAN); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T2 (RO (2, 1), froian, IAN); // { dg-warning "\\\[-Wuninitialized" }
+T2 (RW (2, 1), frwian, IAN); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T2 (WO (2, 1), fwoian, IAN);
+T2 (X (2, 1), fxian, IAN);
+
+
+typedef int* IP;
+typedef const int* CIP;
+
+T1 (NONE, fip, IP);
+T1 (NONE, fcip, CIP); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froip, IP); // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwip, IP); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoip, IP);
+T1 (X (1), fxip, IP);
+
+
+/* Verify that the notes printed after the warning mention attribute
+ access only when the attribute is explicitly used in the declaration
+ and not otherwise. */
+
+void test_note_cst_restrict (void)
+{
+ extern void
+ fccar (const char[restrict]); // { dg-message "by argument 1 of type 'const char\\\[restrict]' to 'fccar'" "note" }
+
+ char a[1]; // { dg-message "'a' declared here" "note" }
+ fccar (a); // { dg-warning "'a' may be used uninitialized" }
+}
+
+void test_note_vla (int n)
+{
+ extern void
+ fccvla (const char[n]); // { dg-message "by argument 1 of type 'const char\\\[n]' to 'fccvla'" "note" }
+
+ char a[2]; // { dg-message "'a' declared here" "note" }
+ fccvla (a); // { dg-warning "'a' may be used uninitialized" }
+}
+
+void test_note_ro (void)
+{
+ extern RO (1) void
+ frocar (char[restrict]); // { dg-message "in a call to 'frocar' declared with attribute 'access \\\(read_only, 1\\\)'" "note" }
+
+ char a[3]; // { dg-message "'a' declared here" "note" }
+ frocar (a); // { dg-warning "'a' is used uninitialized" }
+}
+
+void test_note_rw (void)
+{
+ extern RW (1) void
+ frwcar (char[restrict]); // { dg-message "in a call to 'frwcar' declared with attribute 'access \\\(read_write, 1\\\)'" "note" }
+
+ char a[4]; // { dg-message "'a' declared here" "note" }
+ frwcar (a); // { dg-warning "'a' may be used uninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-4.c b/gcc/testsuite/gcc.dg/auto-init-uninit-4.c
new file mode 100644
index 0000000..482c837
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-4.c
@@ -0,0 +1,52 @@
+/* Spurious uninit variable warnings, case 4.
+ Simplified version of cppexp.c (cpp_parse_expr).
+
+ This one is really fragile, it gets it right if you take out case
+ 1, or if the structure is replaced by an int, or if the structure
+ has fewer members (!) */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+extern void abort (void);
+
+struct operation {
+ short op;
+ char rprio;
+ char flags;
+ char unsignedp;
+ long value;
+};
+
+extern struct operation cpp_lex (void);
+
+void
+cpp_parse_expr (void)
+{
+ int rprio; /* { dg-bogus "rprio" "uninitialized variable warning PR19833" } */
+ struct operation op;
+
+ for (;;)
+ {
+ op = cpp_lex ();
+
+ switch (op.op)
+ {
+ case 0:
+ break;
+ case 1:
+ return;
+ case 2:
+ rprio = 1;
+ break;
+ default:
+ return;
+ }
+
+ if (op.op == 0)
+ return;
+
+ if (rprio != 1)
+ abort();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-5.c b/gcc/testsuite/gcc.dg/auto-init-uninit-5.c
new file mode 100644
index 0000000..ada81c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-5.c
@@ -0,0 +1,39 @@
+/* Spurious uninitialized-variable warnings. */
+/* Disable jump threading, etc to test compiler analysis. */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -fno-tree-dce -fno-tree-vrp -fno-tree-dominator-opts -ftrivial-auto-var-init=zero" } */
+
+extern void use(int);
+extern void foo(void);
+
+void
+func1(int cond)
+{
+ int x; /* { dg-bogus "x" "uninitialized variable warning" } */
+
+ if(cond)
+ x = 1;
+
+ foo();
+
+ if(cond)
+ use(x);
+}
+
+void
+func2 (int cond)
+{
+ int x; /* { dg-bogus "x" "uninitialized variable warning" } */
+ int flag = 0;
+
+ if(cond)
+ {
+ x = 1;
+ flag = 1;
+ }
+
+ foo();
+
+ if(flag)
+ use(x);
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-6.c b/gcc/testsuite/gcc.dg/auto-init-uninit-6.c
new file mode 100644
index 0000000..e6cba4e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-6.c
@@ -0,0 +1,47 @@
+/* Spurious uninitialized variable warnings.
+ This one inspired by java/class.c:build_utf8_ref. */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+#include <stddef.h>
+
+struct tree
+{
+ struct tree *car;
+ struct tree *cdr;
+ int type, data;
+};
+
+extern void *malloc(size_t);
+
+#define INTEGER_T 1
+#define PTR_T 2
+
+#define APPEND(TREE, LAST, TYPE, VALUE) \
+do { \
+ struct tree *tmp = malloc (sizeof (struct tree)); \
+ tmp->car = 0; tmp->cdr = 0; tmp->type = TYPE; \
+ tmp->data = VALUE; \
+ if (TREE->car) \
+ LAST->cdr = tmp; \
+ else \
+ TREE->car = tmp; \
+ LAST = tmp; \
+} while(0)
+
+struct tree *
+make_something(int a, int b, int c)
+{
+ struct tree *rv;
+ struct tree *field;
+
+ rv = malloc (sizeof (struct tree));
+ rv->car = 0;
+
+ APPEND(rv, field, INTEGER_T, a); /* { dg-bogus "field" "uninitialized variable warning" } */
+ APPEND(rv, field, PTR_T, b);
+ APPEND(rv, field, INTEGER_T, c);
+
+ return rv;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-8.c b/gcc/testsuite/gcc.dg/auto-init-uninit-8.c
new file mode 100644
index 0000000..6c29887
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-8.c
@@ -0,0 +1,32 @@
+/* Uninitialized variable warning tests...
+ Inspired by part of optabs.c:expand_binop.
+ May be the same as uninit-1.c. */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+#include <limits.h>
+
+void
+add_bignums (int *out, int *x, int *y)
+{
+ int p, sum;
+ int carry; /* { dg-bogus "carry" "uninitialized variable warning" } */
+
+ p = 0;
+ for (; *x; x++, y++, out++, p++)
+ {
+ if (p)
+ sum = *x + *y + carry;
+ else
+ sum = *x + *y;
+
+ if (sum < 0)
+ {
+ carry = 1;
+ sum -= INT_MAX;
+ }
+ else
+ carry = 0;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-9.c b/gcc/testsuite/gcc.dg/auto-init-uninit-9.c
new file mode 100644
index 0000000..9d65493
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-9.c
@@ -0,0 +1,42 @@
+/* Spurious uninitialized variable warnings. Slight variant on the
+ documented case, inspired by reg-stack.c:record_asm_reg_life. */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+/* { dg-require-effective-target alloca } */
+
+struct foo
+{
+ int type;
+ struct foo *car;
+ struct foo *cdr;
+ char *data;
+ int data2;
+};
+
+extern void use(struct foo *);
+
+#define CLOBBER 6
+#define PARALLEL 3
+
+void
+func(struct foo *list, int count)
+{
+ int n_clobbers = 0;
+ int i;
+ struct foo **clob_list; /* { dg-bogus "clob_list" "uninitialized variable warning" } */
+
+ if(list[0].type == PARALLEL)
+ {
+ clob_list = __builtin_alloca(count * sizeof(struct foo *));
+
+ for(i = 1; i < count; i++)
+ {
+ if(list[i].type == CLOBBER)
+ clob_list[n_clobbers++] = &list[i];
+ }
+ }
+
+ for(i = 0; i < n_clobbers; i++)
+ use(clob_list[i]);
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-A.c b/gcc/testsuite/gcc.dg/auto-init-uninit-A.c
new file mode 100644
index 0000000..01fcf59
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-A.c
@@ -0,0 +1,117 @@
+/* Inspired by part of java/parse.y.
+ May be a real bug in CSE. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -ftrivial-auto-var-init=zero" } */
+
+struct tree
+{
+ struct tree *car, *cdr, *wfl;
+ int code;
+ struct { unsigned int renp:1;
+ unsigned int rtnp:1;
+ unsigned int rpnp:1; } flags;
+};
+typedef struct tree *tree;
+#define NULL_TREE ((tree)0)
+
+/* Codes */
+enum
+{
+ CALL_EXPR, NEW_ARRAY_EXPR, NEW_CLASS_EXPR, CONVERT_EXPR,
+ ARRAY_REF, CONDITIONAL_EXPR, STRING_CST, EXPR_WITH_FILE_LOCATION
+};
+
+/* Flags */
+#define RESOLVE_EXPRESSION_NAME_P(t) ((t)->flags.renp)
+#define RESOLVE_TYPE_NAME_P(t) ((t)->flags.rtnp)
+#define RESOLVE_PACKAGE_NAME_P(t) ((t)->flags.rpnp)
+
+/* Macros */
+#define EXPR_WFL_QUALIFICATION(t) ((t)->wfl)
+#define QUAL_WFL(t) ((t)->wfl)
+#define EXPR_WFL_NODE(t) ((t)->wfl)
+#define TREE_CODE(t) ((t)->code)
+#define TREE_OPERAND(t,x) ((t)->car)
+#define CLASSTYPE_SUPER(t) ((t)->car)
+#define IDENTIFIER_LOCAL_VALUE(t) ((t)->car)
+#define TREE_CHAIN(t) ((t)->cdr)
+#define QUAL_RESOLUTION(t) ((t)->cdr)
+
+extern tree current_class, this_identifier_node;
+extern tree super_identifier_node, length_identifier_node;
+
+tree resolve_and_layout (tree, tree);
+tree lookup_field_wrapper (tree, tree);
+
+void
+qualify_ambiguous_name (id)
+ tree id;
+{
+ tree qual, qual_wfl, decl;
+ tree name; /* { dg-bogus "name" "uninitialized variable warning" } */
+ tree ptr_type; /* { dg-bogus "ptr_type" "uninitialized variable warning" } */
+ int again, new_array_found = 0;
+ int super_found = 0, this_found = 0;
+
+ qual = EXPR_WFL_QUALIFICATION (id);
+ do {
+ qual_wfl = QUAL_WFL (qual);
+ switch (TREE_CODE (qual_wfl))
+ {
+ case CALL_EXPR:
+ qual_wfl = TREE_OPERAND (qual_wfl, 0);
+ if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION)
+ {
+ qual = EXPR_WFL_QUALIFICATION (qual_wfl);
+ qual_wfl = QUAL_WFL (qual);
+ }
+ break;
+ case NEW_ARRAY_EXPR:
+ qual = TREE_CHAIN (qual);
+ new_array_found = again = 1;
+ continue;
+ case NEW_CLASS_EXPR:
+ case CONVERT_EXPR:
+ qual_wfl = TREE_OPERAND (qual_wfl, 0);
+ break;
+ case ARRAY_REF:
+ while (TREE_CODE (qual_wfl) == ARRAY_REF)
+ qual_wfl = TREE_OPERAND (qual_wfl, 0);
+ break;
+ default:
+ break;
+ }
+
+ name = EXPR_WFL_NODE (qual_wfl);
+ ptr_type = current_class;
+ again = 0;
+
+ } while (again);
+
+ /* If you put straightforward uses of name and ptr_type here
+ instead of the if-else sequence below, the warnings go away.
+ Therefore I suspect a real bug. */
+
+ if (!this_found && !super_found && (decl = IDENTIFIER_LOCAL_VALUE (name)))
+ {
+ RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
+ QUAL_RESOLUTION (qual) = decl;
+ }
+ else if ((decl = lookup_field_wrapper (ptr_type, name))
+ || (new_array_found && name == length_identifier_node))
+ {
+ RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
+ QUAL_RESOLUTION (qual) = (new_array_found ? NULL_TREE : decl);
+ }
+ else if ((decl = resolve_and_layout (name, NULL_TREE)))
+ {
+ RESOLVE_TYPE_NAME_P (qual_wfl) = 1;
+ QUAL_RESOLUTION (qual) = decl;
+ }
+ else if (TREE_CODE (QUAL_WFL (qual)) == CALL_EXPR
+ || TREE_CODE (QUAL_WFL (qual)) == ARRAY_REF)
+ RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
+ else
+ RESOLVE_PACKAGE_NAME_P (qual_wfl) = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-B.c b/gcc/testsuite/gcc.dg/auto-init-uninit-B.c
new file mode 100644
index 0000000..0b28371
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-B.c
@@ -0,0 +1,15 @@
+/* Origin: PR c/179 from Gray Watson <gray@256.com>, adapted as a testcase
+ by Joseph Myers <jsm28@cam.ac.uk>. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+extern void foo (int *);
+extern void bar (int);
+
+void
+baz (void)
+{
+ int i;
+ if (i) /* { dg-warning "is used uninitialized" "uninit i warning" } */
+ bar (i);
+ foo (&i);
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-C.c b/gcc/testsuite/gcc.dg/auto-init-uninit-C.c
new file mode 100644
index 0000000..a4aa629
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-C.c
@@ -0,0 +1,21 @@
+/* Spurious uninitialized variable warning, inspired by libgcc2.c. */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+/* Not all platforms support TImode integers. */
+#if defined(__LP64__) && !defined(__hppa__)
+typedef int TItype __attribute__ ((mode (TI)));
+#else
+typedef long TItype;
+#endif
+
+
+TItype
+__subvdi3 (TItype a, TItype b)
+{
+ TItype w;
+
+ w = a - b;
+
+ return w;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-H.c b/gcc/testsuite/gcc.dg/auto-init-uninit-H.c
new file mode 100644
index 0000000..71e2e2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-H.c
@@ -0,0 +1,33 @@
+/* PR 14204 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wall -Werror -ftrivial-auto-var-init=zero" } */
+
+#if defined __alpha__
+# define ASM __asm__("$30")
+#elif defined __i386__
+# define ASM __asm__("esp")
+#elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) || defined (_POWER)
+# define ASM __asm__("r1")
+#elif defined __s390__
+# define ASM __asm__("r15")
+#elif defined __mips
+# define ASM __asm__("$sp")
+#elif defined __sparc__
+# define ASM __asm__("sp")
+#elif defined __ia64__
+# define ASM __asm__("r12")
+#elif defined __hppa__
+# define ASM __asm__("%r30")
+#elif defined __xtensa__
+# define ASM __asm__("sp")
+#else
+/* The register name should be target-dependent so for other targets,
+ we just silence the test. */
+# define ASM = 0
+#endif
+
+void *load_PCB (void)
+{
+ register void *sp ASM;
+ return sp; /* { dg-bogus "uninitialized" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-I.c b/gcc/testsuite/gcc.dg/auto-init-uninit-I.c
new file mode 100644
index 0000000..09680fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-I.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+int sys_msgctl (void)
+{
+ struct { int mode; } setbuf;
+ return setbuf.mode; /* { dg-warning "'setbuf\.mode' is used" } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-1.c b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c
new file mode 100644
index 0000000..0fa4708
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 11 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-10.c b/gcc/testsuite/gcc.target/aarch64/auto-init-10.c
new file mode 100644
index 0000000..aceceb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-10.c
@@ -0,0 +1,18 @@
+/* Verify pattern initialization for structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_aligned {
+ int internal1;
+ long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+ struct test_aligned var;
+ return var.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 2 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-11.c b/gcc/testsuite/gcc.target/aarch64/auto-init-11.c
new file mode 100644
index 0000000..085c386
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-11.c
@@ -0,0 +1,27 @@
+/* Verify zero initialization for nested structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+ unsigned internal1;
+ unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+ char one;
+ char two;
+ char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+ struct test_big_hole var;
+ return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 4 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-12.c b/gcc/testsuite/gcc.target/aarch64/auto-init-12.c
new file mode 100644
index 0000000..5d1383b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-12.c
@@ -0,0 +1,27 @@
+/* Verify pattern initialization for nested structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_aligned {
+ unsigned internal1;
+ unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+ char one;
+ char two;
+ char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+ struct test_big_hole var;
+ return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 4 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-13.c b/gcc/testsuite/gcc.target/aarch64/auto-init-13.c
new file mode 100644
index 0000000..3c45a6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-13.c
@@ -0,0 +1,22 @@
+/* Verify zero initialization for structure type automatic variables with
+ tail padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var;
+ return var.four;
+}
+
+/* { dg-final { scan-assembler-times "stp\txzr, xzr," 2 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-14.c b/gcc/testsuite/gcc.target/aarch64/auto-init-14.c
new file mode 100644
index 0000000..500020e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-14.c
@@ -0,0 +1,20 @@
+/* Verify pattern initialization for structure type automatic variables with
+ tail padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var;
+ return var.four;
+}
+
+/* { dg-final { scan-assembler-times "stp\txzr, xzr," 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-15.c b/gcc/testsuite/gcc.target/aarch64/auto-init-15.c
new file mode 100644
index 0000000..cb96c3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-15.c
@@ -0,0 +1,20 @@
+/* Verify zero initialization for structure type automatic variables with
+ padding and has explicit initialization. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+ return var.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-16.c b/gcc/testsuite/gcc.target/aarch64/auto-init-16.c
new file mode 100644
index 0000000..ce7c7cd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-16.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for structure type automatic variables with
+ padding and has explicit initialization. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+ return var.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
+
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-17.c b/gcc/testsuite/gcc.target/aarch64/auto-init-17.c
new file mode 100644
index 0000000..c81e5ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-17.c
@@ -0,0 +1,21 @@
+/* Verify zero initialization for array type with structure element with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+ struct test_trailing_hole var[10];
+ return var[2].four;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 5 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-18.c b/gcc/testsuite/gcc.target/aarch64/auto-init-18.c
new file mode 100644
index 0000000..0ec0ac4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-18.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for array type with structure element with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+ struct test_trailing_hole var[10];
+ return var[2].four;
+}
+
+/* { dg-final { scan-assembler-times "str\tw0, " 30 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-19.c b/gcc/testsuite/gcc.target/aarch64/auto-init-19.c
new file mode 100644
index 0000000..02f7edc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-19.c
@@ -0,0 +1,27 @@
+/* Verify zero initialization for union type with structure field with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+ struct test_trailing_hole u1;
+ long long u2;
+};
+
+
+int foo ()
+{
+ union test_union_padding var;
+ return var.u1.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-2.c b/gcc/testsuite/gcc.target/aarch64/auto-init-2.c
new file mode 100644
index 0000000..2cbe34e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-2.c
@@ -0,0 +1,37 @@
+/* Verify pattern initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xffffffffffffffaa" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xffffffffffffaaaa" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xffffffffaaaaaaaa" 2 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xaaaaaaaaaaaaaaaa" 3 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "const_int 0" 4 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-20.c b/gcc/testsuite/gcc.target/aarch64/auto-init-20.c
new file mode 100644
index 0000000..0ef9acd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-20.c
@@ -0,0 +1,27 @@
+/* Verify pattern initialization for union type with structure field with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+ struct test_trailing_hole u1;
+ long long u2;
+};
+
+
+int foo ()
+{
+ union test_union_padding var;
+ return var.u1.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-3.c b/gcc/testsuite/gcc.target/aarch64/auto-init-3.c
new file mode 100644
index 0000000..78291a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-3.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump "const_double:SF 0.0" "expand" } } */
+/* { dg-final { scan-rtl-dump "const_double:DF 0.0" "expand" } } */
+/* { dg-final { scan-rtl-dump "const_double:TF 0.0" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-4.c b/gcc/testsuite/gcc.target/aarch64/auto-init-4.c
new file mode 100644
index 0000000..53b8203
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-4.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump "const_double:SF \\+QNaN" "expand" } } */
+/* { dg-final { scan-rtl-dump "const_double:DF \\+QNaN" "expand" } } */
+/* { dg-final { scan-rtl-dump "const_double:TF \\+QNaN" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-5.c b/gcc/testsuite/gcc.target/aarch64/auto-init-5.c
new file mode 100644
index 0000000..092f83e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-5.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-assembler-times ".word\\t0" 14 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-6.c b/gcc/testsuite/gcc.target/aarch64/auto-init-6.c
new file mode 100644
index 0000000..8cea598
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-6.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-assembler-times ".word\\t2143289344" 2 } } */
+/* { dg-final { scan-assembler-times ".word\\t2146959360" 2 } } */
+/* { dg-final { scan-assembler-times ".word\\t2147450880" 2 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-7.c b/gcc/testsuite/gcc.target/aarch64/auto-init-7.c
new file mode 100644
index 0000000..ac27fbe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-7.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 8 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-8.c b/gcc/testsuite/gcc.target/aarch64/auto-init-8.c
new file mode 100644
index 0000000..2f1de12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-8.c
@@ -0,0 +1,33 @@
+/* Verify pattern initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xffffffffaaaaaaaa" 4 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xffffffffffffffaa" 25 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-9.c b/gcc/testsuite/gcc.target/aarch64/auto-init-9.c
new file mode 100644
index 0000000..7294de5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-9.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+ int internal1;
+ long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+ struct test_aligned var;
+ return var.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 2 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-1.c b/gcc/testsuite/gcc.target/i386/auto-init-1.c
new file mode 100644
index 0000000..b7690df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-1.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 10 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-10.c b/gcc/testsuite/gcc.target/i386/auto-init-10.c
new file mode 100644
index 0000000..88f95b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-10.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_aligned {
+ int internal1;
+ long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+ struct test_aligned var;
+ return var.internal1;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 8 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-11.c b/gcc/testsuite/gcc.target/i386/auto-init-11.c
new file mode 100644
index 0000000..8a6d764
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-11.c
@@ -0,0 +1,30 @@
+/* Verify zero initialization for nested structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+ unsigned internal1;
+ unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+ char one;
+ char two;
+ char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+ struct test_big_hole var;
+ return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler "movl\t\\\$0," } } */
+/* { dg-final { scan-assembler "movl\t\\\$16," } } */
+/* { dg-final { scan-assembler "rep stosq" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-12.c b/gcc/testsuite/gcc.target/i386/auto-init-12.c
new file mode 100644
index 0000000..b5a7bd4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-12.c
@@ -0,0 +1,30 @@
+/* Verify pattern initialization for nested structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_aligned {
+ unsigned internal1;
+ unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+ char one;
+ char two;
+ char three;
+ /* 61 byte padding hole here. */
+ struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+ struct test_big_hole var;
+ return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler "movl\t\\\$0," } } */
+/* { dg-final { scan-assembler "movl\t\\\$16," } } */
+/* { dg-final { scan-assembler "rep stosq" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-13.c b/gcc/testsuite/gcc.target/i386/auto-init-13.c
new file mode 100644
index 0000000..e18bc30
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-13.c
@@ -0,0 +1,22 @@
+/* Verify zero initialization for structure type automatic variables with
+ tail padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var;
+ return var.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 4 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-14.c b/gcc/testsuite/gcc.target/i386/auto-init-14.c
new file mode 100644
index 0000000..55a4c9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-14.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for structure type automatic variables with
+ tail padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+ char *one;
+ char *two;
+ char *three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var;
+ return var.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 4 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-15.c b/gcc/testsuite/gcc.target/i386/auto-init-15.c
new file mode 100644
index 0000000..b5abffb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-15.c
@@ -0,0 +1,22 @@
+/* Verify zero initialization for structure type automatic variables with
+ padding and has explicit initialization. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+ return var.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 2 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-16.c b/gcc/testsuite/gcc.target/i386/auto-init-16.c
new file mode 100644
index 0000000..66591cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-16.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for structure type automatic variables with
+ padding and has explicit initialization. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+ struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+ return var.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 2 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-17.c b/gcc/testsuite/gcc.target/i386/auto-init-17.c
new file mode 100644
index 0000000..40fccad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-17.c
@@ -0,0 +1,23 @@
+/* Verify zero initialization for array type with structure element with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+ struct test_trailing_hole var[10];
+ return var[2].four;
+}
+
+/* { dg-final { scan-assembler "movl\t\\\$0," } } */
+/* { dg-final { scan-assembler "movl\t\\\$20," } } */
+/* { dg-final { scan-assembler "rep stosq" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-18.c b/gcc/testsuite/gcc.target/i386/auto-init-18.c
new file mode 100644
index 0000000..a422a8d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-18.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for array type with structure element with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+ struct test_trailing_hole var[10];
+ return var[2].four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 20 } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-19.c b/gcc/testsuite/gcc.target/i386/auto-init-19.c
new file mode 100644
index 0000000..31a3ee1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-19.c
@@ -0,0 +1,26 @@
+/* Verify zero initialization for union type with structure field with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+ struct test_trailing_hole u1;
+ long long u2;
+};
+
+
+int foo ()
+{
+ union test_union_padding var;
+ return var.u1.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-2.c b/gcc/testsuite/gcc.target/i386/auto-init-2.c
new file mode 100644
index 0000000..c7e006e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-2.c
@@ -0,0 +1,37 @@
+/* Verify pattern initialization for integer and pointer type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+ N1 = 0,
+ N2,
+ N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+ char temp1;
+ short temp2;
+ int temp3;
+ enum E temp4;
+ long temp5;
+ long long temp6;
+ int *temp7;
+ bool temp8;
+
+ bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+ return;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xffffffffffffffaa" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xffffffffffffaaaa" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xffffffffaaaaaaaa" 2 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xaaaaaaaaaaaaaaaa" 3 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "const_int 0" 3 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-20.c b/gcc/testsuite/gcc.target/i386/auto-init-20.c
new file mode 100644
index 0000000..e675e8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-20.c
@@ -0,0 +1,26 @@
+/* Verify pattern initialization for union type with structure field with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+ int one;
+ int two;
+ int three;
+ char four;
+ /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+ struct test_trailing_hole u1;
+ long long u2;
+};
+
+
+int foo ()
+{
+ union test_union_padding var;
+ return var.u1.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-3.c b/gcc/testsuite/gcc.target/i386/auto-init-3.c
new file mode 100644
index 0000000..0771f4f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-3.c
@@ -0,0 +1,20 @@
+/* Verify zero initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */
+/* { dg-final { scan-assembler "movss\[ \t\]+%xmm0" } } */
+/* { dg-final { scan-assembler "movsd\[ \t\]+%xmm0" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-4.c b/gcc/testsuite/gcc.target/i386/auto-init-4.c
new file mode 100644
index 0000000..4001e2c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-4.c
@@ -0,0 +1,23 @@
+/* Verify pattern initialization for floating point type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+long double result;
+
+long double foo()
+{
+ float temp1;
+ double temp2;
+ long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-assembler "movss\[ \t\]+.LC0\\(%rip\\), %xmm0" } } */
+/* { dg-final { scan-assembler "movss\[ \t\]+%xmm0" } } */
+/* { dg-final { scan-assembler "movsd\[ \t\]+.LC1\\(%rip\\), %xmm0" } } */
+/* { dg-final { scan-assembler "movsd\[ \t\]+%xmm0" } } */
+/* { dg-final { scan-assembler ".long\[ \t\]+2143289344" } } */
+/* { dg-final { scan-assembler ".long\[ \t\]+2146959360" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-5.c b/gcc/testsuite/gcc.target/i386/auto-init-5.c
new file mode 100644
index 0000000..c24a6fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-5.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-assembler-times ".long\\t0" 14 } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-6.c b/gcc/testsuite/gcc.target/i386/auto-init-6.c
new file mode 100644
index 0000000..3f17113
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-6.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for complex type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+ _Complex float temp1;
+ _Complex double temp2;
+ _Complex long double temp3;
+
+ result = temp1 + temp2 + temp3;
+ return result;
+}
+
+/* { dg-final { scan-assembler-times ".long\\t2143289344" 3 } } */
+/* { dg-final { scan-assembler-times ".long\\t2146959360" 2 } } */
+/* { dg-final { scan-assembler-times ".long\\t-1073741824" 2 } } */
+/* { dg-final { scan-assembler-times ".long\\t32767" 2 } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-7.c b/gcc/testsuite/gcc.target/i386/auto-init-7.c
new file mode 100644
index 0000000..ac27fbe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-7.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 8 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-8.c b/gcc/testsuite/gcc.target/i386/auto-init-8.c
new file mode 100644
index 0000000..ef5ab31
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-8.c
@@ -0,0 +1,33 @@
+/* Verify pattern initialization for array, union, and structure type automatic variables. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct S
+{
+ int f1;
+ float f2;
+ char f3[20];
+};
+
+union U
+{
+ char u1[5];
+ int u2;
+ float u3;
+};
+
+double result;
+
+double foo()
+{
+ int temp1[3];
+ double temp2[3];
+ struct S temp3;
+ union U temp4;
+
+ result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+ return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xffffffffaaaaaaaa" 4 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xffffffffffffffaa" 26 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-9.c b/gcc/testsuite/gcc.target/i386/auto-init-9.c
new file mode 100644
index 0000000..b406979
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-9.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for structure type automatic variables with
+ padding. */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+ int internal1;
+ long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+ struct test_aligned var;
+ return var.internal1;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 8 } } */
+
+
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 7e3aae5..da02be2 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3471,6 +3471,9 @@ verify_gimple_call (gcall *stmt)
}
}
+ if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+ return false;
+
/* ??? The C frontend passes unpromoted arguments in case it
didn't see a function declaration before the call. So for now
leave the call arguments mostly unverified. Once we gimplify
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index d2e6c89..fb42c41 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1815,6 +1815,7 @@ struct GTY(()) tree_decl_with_vis {
unsigned in_text_section : 1;
unsigned in_constant_pool : 1;
unsigned dllimport_flag : 1;
+ unsigned uninitialized : 1;
/* Don't belong to VAR_DECL exclusively. */
unsigned weak_flag : 1;
@@ -1836,7 +1837,7 @@ struct GTY(()) tree_decl_with_vis {
unsigned final : 1;
/* Belong to FUNCTION_DECL exclusively. */
unsigned regdecl_flag : 1;
- /* 14 unused bits. */
+ /* 13 unused bits. */
/* 32 more unused on 64 bit HW. */
};
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index d177f1b..fe439f7 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -384,6 +384,13 @@ static struct
/* Numbber of components created when splitting aggregate parameters. */
int param_reductions_created;
+
+ /* Number of deferred_init calls that are modified. */
+ int deferred_init;
+
+ /* Number of deferred_init calls that are created by
+ generate_subtree_deferred_init. */
+ int subtree_deferred_init;
} sra_stats;
static void
@@ -4070,6 +4077,105 @@ get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
}
+
+/* Generate statements to call .DEFERRED_INIT to initialize scalar replacements
+ of accesses within a subtree ACCESS, all its children, siblings and their
+ children are to be processed. TOP_OFFSET is the offset of the processed
+ subtree which has to be subtracted from offsets of individual accesses to
+ get corresponding offsets for AGG. GSI is a statement iterator used to place
+ the new statements. */
+static void
+generate_subtree_deferred_init (struct access *access, tree agg,
+ enum auto_init_type init_type,
+ HOST_WIDE_INT top_offset,
+ gimple_stmt_iterator *gsi,
+ location_t loc)
+{
+ do
+ {
+ if (access->grp_to_be_replaced)
+ {
+ tree repl = get_access_replacement (access);
+ tree init_type_node
+ = build_int_cst (integer_type_node, (int) init_type);
+ gimple *call = gimple_build_call_internal (IFN_DEFERRED_INIT, 2,
+ repl, init_type_node);
+ gimple_call_set_lhs (call, repl);
+ gsi_insert_before (gsi, call, GSI_SAME_STMT);
+ update_stmt (call);
+ gimple_set_location (call, loc);
+
+ sra_stats.subtree_deferred_init++;
+ }
+ else if (access->grp_to_be_debug_replaced)
+ {
+ /* FIXME, this part might have some issue. */
+ tree drhs = build_debug_ref_for_model (loc, agg,
+ access->offset - top_offset,
+ access);
+ gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
+ drhs, gsi_stmt (*gsi));
+ gsi_insert_before (gsi, ds, GSI_SAME_STMT);
+ }
+ if (access->first_child)
+ generate_subtree_deferred_init (access->first_child, agg, init_type,
+ top_offset, gsi, loc);
+
+ access = access ->next_sibling;
+ }
+ while (access);
+}
+
+/* For a call to .DEFERRED_INIT:
+ var = .DEFERRED_INIT (var, init_type);
+ examine the LHS variable VAR and replace it with a scalar replacement if
+ there is one, also replace the RHS call to a call to .DEFERRED_INIT of
+ the corresponding scalar relacement variable. Examine the subtree and
+ do the scalar replacements in the subtree too. STMT is the call, GSI is
+ the statment iterator to place newly created statements. */
+
+static enum assignment_mod_result
+sra_modify_deferred_init (gimple *stmt, gimple_stmt_iterator *gsi)
+{
+ tree lhs = gimple_call_lhs (stmt);
+ enum auto_init_type init_type
+ = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
+ struct access *access = get_access_for_expr (lhs);
+ if (!access)
+ return SRA_AM_NONE;
+ location_t loc = gimple_location (stmt);
+
+ if (access->grp_to_be_replaced)
+ {
+ tree repl = get_access_replacement (access);
+ gimple_call_set_lhs (stmt, repl);
+ gimple_call_set_arg (stmt, 0, repl);
+ sra_stats.deferred_init++;
+ }
+ else if (access->grp_to_be_debug_replaced)
+ {
+ /* FIXME, this part might have some issues. */
+ tree drepl = get_access_replacement (access);
+ gdebug *ds = gimple_build_debug_bind (drepl, NULL_TREE,
+ gsi_stmt (*gsi));
+ gsi_insert_before (gsi, ds, GSI_SAME_STMT);
+ }
+
+ if (access->first_child)
+ generate_subtree_deferred_init (access->first_child, lhs,
+ init_type, access->offset,
+ gsi, loc);
+ if (access->grp_covered)
+ {
+ unlink_stmt_vdef (stmt);
+ gsi_remove (gsi, true);
+ release_defs (stmt);
+ return SRA_AM_REMOVED;
+ }
+
+ return SRA_AM_MODIFIED;
+}
+
/* Examine both sides of the assignment statement pointed to by STMT, replace
them with a scalare replacement if there is one and generate copying of
replacements if scalarized aggregates have been used in the assignment. GSI
@@ -4434,17 +4540,27 @@ sra_modify_function_body (void)
break;
case GIMPLE_CALL:
- /* Operands must be processed before the lhs. */
- for (i = 0; i < gimple_call_num_args (stmt); i++)
+ /* Handle calls to .DEFERRED_INIT specially. */
+ if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
{
- t = gimple_call_arg_ptr (stmt, i);
- modified |= sra_modify_expr (t, &gsi, false);
+ assign_result = sra_modify_deferred_init (stmt, &gsi);
+ modified |= assign_result == SRA_AM_MODIFIED;
+ deleted = assign_result == SRA_AM_REMOVED;
}
-
- if (gimple_call_lhs (stmt))
+ else
{
- t = gimple_call_lhs_ptr (stmt);
- modified |= sra_modify_expr (t, &gsi, true);
+ /* Operands must be processed before the lhs. */
+ for (i = 0; i < gimple_call_num_args (stmt); i++)
+ {
+ t = gimple_call_arg_ptr (stmt, i);
+ modified |= sra_modify_expr (t, &gsi, false);
+ }
+
+ if (gimple_call_lhs (stmt))
+ {
+ t = gimple_call_lhs_ptr (stmt);
+ modified |= sra_modify_expr (t, &gsi, true);
+ }
}
break;
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 529ec3a..dc325aa 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -4863,6 +4863,29 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t)
return false;
}
+static void
+find_func_aliases_for_deferred_init (gcall *t)
+{
+ tree lhsop = gimple_call_lhs (t);
+ enum auto_init_type init_type
+ = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (t, 1));
+ auto_vec<ce_s, 2> lhsc;
+ auto_vec<ce_s, 4> rhsc;
+ struct constraint_expr temp;
+
+ get_constraint_for (lhsop, &lhsc);
+ if (init_type == AUTO_INIT_ZERO && flag_delete_null_pointer_checks)
+ temp.var = nothing_id;
+ else
+ temp.var = nonlocal_id;
+ temp.type = ADDRESSOF;
+ temp.offset = 0;
+ rhsc.safe_push (temp);
+
+ process_all_all_constraints (lhsc, rhsc);
+ return;
+}
+
/* Create constraints for the call T. */
static void
@@ -4876,6 +4899,12 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
&& find_func_aliases_for_builtin_call (fn, t))
return;
+ if (gimple_call_internal_p (t, IFN_DEFERRED_INIT))
+ {
+ find_func_aliases_for_deferred_init (t);
+ return;
+ }
+
fi = get_fi_for_callee (t);
if (!in_ipa_mode
|| (fi->decl && fndecl && !fi->is_fn_info))
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 0800f59..0c61f60 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -135,6 +135,20 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
if (is_gimple_assign (context)
&& gimple_assign_rhs_code (context) == COMPLEX_EXPR)
return;
+
+ /* Ignore REALPART_EXPR or IMAGPART_EXPR if its operand is
+ a call to .DEFERRED_INIT. */
+ if (is_gimple_assign (context)
+ && (gimple_assign_rhs_code (context) == REALPART_EXPR
+ || gimple_assign_rhs_code (context) == IMAGPART_EXPR))
+ {
+ tree v = gimple_assign_rhs1 (context);
+ if (TREE_CODE (TREE_OPERAND (v, 0)) == SSA_NAME
+ && gimple_call_internal_p (SSA_NAME_DEF_STMT (TREE_OPERAND (v, 0)),
+ IFN_DEFERRED_INIT))
+ return;
+ }
+
if (!has_undefined_value_p (t))
return;
@@ -209,6 +223,19 @@ check_defs (ao_ref *ref, tree vdef, void *data_)
{
check_defs_data *data = (check_defs_data *)data_;
gimple *def_stmt = SSA_NAME_DEF_STMT (vdef);
+
+ /* Ignore the vdef iff the definition statement is a call
+ to .DEFERRED_INIT function. */
+ if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
+ return false;
+
+ /* Ignore the vdef iff the definition statement is a call
+ to builtin_memset function that is added for uninitialized
+ auto variable initialization. */
+ if (gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET)
+ && gimple_call_memset_for_uninit_p (def_stmt))
+ return false;
+
/* If this is a clobber then if it is not a kill walk past it. */
if (gimple_clobber_p (def_stmt))
{
@@ -611,6 +638,9 @@ warn_uninitialized_vars (bool wmaybe_uninit)
ssa_op_iter op_iter;
tree use;
+ if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+ continue;
+
if (is_gimple_debug (stmt))
continue;
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index cf54c89..93d6124 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1325,6 +1325,23 @@ ssa_undefined_value_p (tree t, bool partial)
if (gimple_nop_p (def_stmt))
return true;
+ /* The value is undefined iff the definition statement is a call
+ to .DEFERRED_INIT function. */
+ if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
+ return true;
+
+ if (partial && is_gimple_assign (def_stmt)
+ && (gimple_assign_rhs_code (def_stmt) == REALPART_EXPR
+ || gimple_assign_rhs_code (def_stmt) == IMAGPART_EXPR))
+ {
+ tree real_imag_part = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0);
+ if (TREE_CODE (real_imag_part) == SSA_NAME
+ && gimple_call_internal_p (SSA_NAME_DEF_STMT (real_imag_part),
+ IFN_DEFERRED_INIT))
+ return true;
+ }
+
+
/* Check if the complex was not only partially defined. */
if (partial && is_gimple_assign (def_stmt)
&& gimple_assign_rhs_code (def_stmt) == COMPLEX_EXPR)
diff --git a/gcc/tree.c b/gcc/tree.c
index 7c44c22..2c9acad 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2531,6 +2531,144 @@ build_zero_cst (tree type)
}
}
+/* Build pattern constant of type TYPE. This is used for initializing
+ auto variables. */
+
+tree
+build_pattern_cst (tree type)
+{
+ /* The following value is a guaranteed unmappable pointer value and has a
+ repeated byte-pattern which makes it easier to synthesize. We use it for
+ pointers as well as integers so that aggregates are likely to be
+ initialized with this repeated value. */
+ uint64_t largevalue = 0xAAAAAAAAAAAAAAAAull;
+ /* For 32-bit platforms it's a bit trickier because, across systems, only the
+ zero page can reasonably be expected to be unmapped, and even then we need
+ a very low address. We use a smaller value, and that value sadly doesn't
+ have a repeated byte-pattern. We don't use it for integers. */
+ uint32_t smallvalue = 0x000000AA;
+
+ switch (TREE_CODE (type))
+ {
+ case INTEGER_TYPE:
+ case ENUMERAL_TYPE:
+ case BOOLEAN_TYPE:
+ /* This will initialize a boolean type variable to 0 instead of 1.
+ We think that initializint a boolean variable to 0 other than 1
+ is better even for pattern initialization. */
+ return build_int_cstu (type, largevalue);
+ case POINTER_TYPE:
+ case OFFSET_TYPE:
+ case REFERENCE_TYPE:
+ case NULLPTR_TYPE:
+ {
+ poly_uint64 intvalue;
+
+ if (POINTER_SIZE == 64)
+ intvalue = largevalue;
+ else if (POINTER_SIZE == 32)
+ intvalue = smallvalue;
+ else
+ gcc_assert (0);
+ return build_int_cstu (type, intvalue);
+ }
+ case REAL_TYPE:
+ {
+ REAL_VALUE_TYPE rnan;
+
+ /* create an quiet NAN for REAL TYPE. */
+ if (real_nan (&rnan, "", 1, TYPE_MODE (type)))
+ return build_real (type, rnan);
+ return NULL_TREE;
+ }
+
+ case FIXED_POINT_TYPE:
+ {
+ /* FIXME. What should we put into a fixed point? */
+ FIXED_VALUE_TYPE fixed;
+ fixed_from_string (&fixed, "0xFFFFFFFFFFFFFFFF",
+ SCALAR_TYPE_MODE (type));
+ return build_fixed (type, fixed);
+ }
+ case VECTOR_TYPE:
+ {
+ tree scalar = build_pattern_cst (TREE_TYPE (type));
+ return build_vector_from_val (type, scalar);
+ }
+ case COMPLEX_TYPE:
+ {
+ tree element = build_pattern_cst (TREE_TYPE (type));
+ return build_complex (type, element, element);
+ }
+ case RECORD_TYPE:
+ {
+ tree field;
+ tree field_value;
+ vec<constructor_elt, va_gc> *v = NULL;
+ for (field= TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+ /* if the field is a variable length array, it should be the last
+ field of the record, and no need to initialize. */
+ if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
+ && TYPE_SIZE (TREE_TYPE (field)) == NULL_TREE
+ && ((TYPE_DOMAIN (TREE_TYPE (field)) != NULL_TREE
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field)))
+ == NULL_TREE)
+ || TYPE_DOMAIN (TREE_TYPE (field)) == NULL_TREE))
+ continue;
+ field_value = build_pattern_cst (TREE_TYPE (field));
+ CONSTRUCTOR_APPEND_ELT (v, field, field_value);
+ }
+ return build_constructor (type, v);
+ }
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ {
+ tree field, max_field = NULL;
+ unsigned max_size = 0;
+ tree field_value;
+ vec<constructor_elt, va_gc> *v = NULL;
+ /* find the field with the largest size. */
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+ if (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field))) >= max_size)
+ {
+ max_size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
+ max_field = field;
+ }
+ }
+ field_value = build_pattern_cst (TREE_TYPE (max_field));
+ CONSTRUCTOR_APPEND_ELT (v, max_field, field_value);
+ return build_constructor (type, v);
+ }
+ case ARRAY_TYPE:
+ {
+ vec<constructor_elt, va_gc> *elts = NULL;
+ tree element = build_pattern_cst (TREE_TYPE (type));
+ tree nelts = array_type_nelts (type);
+ if (nelts && tree_fits_uhwi_p (nelts))
+ {
+ unsigned HOST_WIDE_INT n = tree_to_uhwi (nelts) + 1;
+ for (unsigned int i = 0; i < n; i++)
+ CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, element);
+ return build_constructor (type, elts);
+ }
+ /* variable length array should not be here. */
+ gcc_assert (0);
+ }
+ default:
+ if (!AGGREGATE_TYPE_P (type))
+ return fold_convert (type, build_pattern_cst (unsigned_type_node));
+ else
+ gcc_assert (0);
+
+ }
+}
+
/* Build a BINFO with LEN language slots. */
@@ -11950,6 +12088,72 @@ lower_bound_in_type (tree outer, tree inner)
}
}
+/* Returns true when the given TYPE has padding inside it.
+ return false otherwise. */
+bool
+type_has_padding (tree type)
+{
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ {
+ unsigned HOST_WIDE_INT record_size
+ = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ unsigned HOST_WIDE_INT size_sofar = 0;
+
+ for (tree field= TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+ unsigned HOST_WIDE_INT cur_off = int_byte_position (field);
+ if (size_sofar < cur_off)
+ return true;
+ size_sofar = cur_off
+ + tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
+ }
+ if (size_sofar < record_size)
+ return true;
+ /* If any of the field has padding, return true. */
+ for (tree field= TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if ((TREE_CODE (field) != FIELD_DECL))
+ continue;
+ if (AGGREGATE_TYPE_P (TREE_TYPE (field))
+ && type_has_padding (TREE_TYPE (field)))
+ return true;
+ }
+ return false;
+ }
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ {
+ tree max_field = NULL;
+ unsigned max_size = 0;
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+ if (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field))) >= max_size)
+ {
+ max_size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
+ max_field = field;
+ }
+ }
+ if (AGGREGATE_TYPE_P (TREE_TYPE (max_field)))
+ return type_has_padding (TREE_TYPE (max_field));
+ return false;
+ }
+ case ARRAY_TYPE:
+ {
+ if (AGGREGATE_TYPE_P (TREE_TYPE (type)))
+ return type_has_padding (TREE_TYPE (type));
+ return false;
+ }
+ default:
+ return false;
+ }
+}
+
/* Return nonzero if two operands that are suitable for PHI nodes are
necessarily equal. Specifically, both ARG0 and ARG1 must be either
SSA_NAME or invariant. Note that this is strictly an optimization.
diff --git a/gcc/tree.h b/gcc/tree.h
index f00ea2e..4d87002 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2892,6 +2892,10 @@ extern void decl_value_expr_insert (tree, tree);
#define DECL_HARD_REGISTER(NODE) \
(VAR_DECL_CHECK (NODE)->decl_with_vis.hard_register)
+/* In a VAR_DECL, nonzero if the decl is intentionly not initialized. */
+#define DECL_UNINITIALIZED(NODE) \
+ (VAR_DECL_CHECK (NODE)->decl_with_vis.uninitialized)
+
/* Used to indicate that this DECL has weak linkage. */
#define DECL_WEAK(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.weak_flag)
@@ -4478,6 +4482,7 @@ extern tree build_one_cst (tree);
extern tree build_minus_one_cst (tree);
extern tree build_all_ones_cst (tree);
extern tree build_zero_cst (tree);
+extern tree build_pattern_cst (tree);
extern tree build_string (unsigned, const char * = NULL);
extern tree build_poly_int_cst (tree, const poly_wide_int_ref &);
extern tree build_tree_list (tree, tree CXX_MEM_STAT_INFO);
@@ -5145,6 +5150,7 @@ extern bool operation_can_overflow (enum tree_code);
extern bool operation_no_trapping_overflow (tree, enum tree_code);
extern tree upper_bound_in_type (tree, tree);
extern tree lower_bound_in_type (tree, tree);
+extern bool type_has_padding (tree);
extern int operand_equal_for_phi_arg_p (const_tree, const_tree);
extern tree create_artificial_label (location_t);
extern const char *get_name (tree);
--
1.8.3.1
[-- Attachment #3: Type: text/plain, Size: 2 bytes --]
next reply other threads:[~2021-03-24 21:22 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-24 21:21 Qing Zhao [this message]
2021-04-07 14:44 ` Qing Zhao
2021-04-07 22:19 ` Kees Cook
2021-04-08 15:22 ` Qing Zhao
2021-04-23 19:05 ` Richard Sandiford
2021-04-23 19:33 ` Kees Cook
2021-04-26 15:09 ` Qing Zhao
2021-04-26 17:47 ` Richard Sandiford
2021-04-26 20:02 ` Qing Zhao
2021-04-27 6:30 ` Richard Biener
2021-04-27 15:10 ` Qing Zhao
2021-05-05 17:29 ` Qing Zhao
2021-05-05 14:41 ` Qing Zhao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0CE28536-176B-44E1-BDC6-3942739B829C@oracle.com \
--to=qing.zhao@oracle.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=keescook@chromium.org \
--cc=rguenther@suse.de \
--cc=richard.sandiford@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).