From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 114801 invoked by alias); 23 Oct 2018 08:59:32 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 114766 invoked by uid 89); 23 Oct 2018 08:59:31 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS autolearn=ham version=3.3.2 spammy=old-deja, olddeja, 85, sk:tf_warn X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 23 Oct 2018 08:59:28 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 8F839ACCC; Tue, 23 Oct 2018 08:59:26 +0000 (UTC) Subject: [PATCH] Make __PRETTY_FUNCTION__-like functions mergeable string csts (PR c++/64266). From: =?UTF-8?Q?Martin_Li=c5=a1ka?= To: Jason Merrill Cc: Jakub Jelinek , Pedro Alves , Jan Kratochvil , GCC Patches , Segher Boessenkool , wilson@gcc.gnu.org, Nathan Sidwell References: <20170425115827.GX1809@tucnak> <3b197eef-db36-7df9-417e-e17be0616b6c@suse.cz> <3f912b8a-0153-f559-e3fe-489b57800697@redhat.com> <894565dc-5c64-cb9f-8bb4-35ee7035c075@suse.cz> <47548cbc-69c9-d925-a107-891a960a2cd1@suse.cz> <714daf75-8c45-2503-23cc-675a7c258485@suse.cz> Message-ID: <7b6f3ceb-d303-4b45-5740-0f4a0f3059cf@suse.cz> Date: Tue, 23 Oct 2018 09:11:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 MIME-Version: 1.0 In-Reply-To: <714daf75-8c45-2503-23cc-675a7c258485@suse.cz> Content-Type: multipart/mixed; boundary="------------3F506F183B3C867AD8B20530" X-IsSubscribed: yes X-SW-Source: 2018-10/txt/msg01399.txt.bz2 This is a multi-part message in MIME format. --------------3F506F183B3C867AD8B20530 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-length: 6726 Hi. I've returned to this long-lasting issue after quite some time. Thanks to Honza I hope I can now address the root cause which caused output of a string constant when debug info was emitted. The problematic situation happened with following back-trace: #0 mergeable_string_section (decl=, align=64, flags=0) at /home/marxin/Programming/gcc/gcc/varasm.c:808 #1 0x0000000001779bf3 in default_elf_select_section (decl=, reloc=0, align=64) at /home/marxin/Programming/gcc/gcc/varasm.c:6739 #2 0x000000000176efb6 in get_constant_section (exp=, align=64) at /home/marxin/Programming/gcc/gcc/varasm.c:3302 #3 0x000000000176f468 in build_constant_desc (exp=) at /home/marxin/Programming/gcc/gcc/varasm.c:3371 #4 0x000000000176f81c in output_constant_def (exp=, defer=1) at /home/marxin/Programming/gcc/gcc/varasm.c:3434 #5 0x000000000176d406 in decode_addr_const (exp=, value=0x7fffffffc540) at /home/marxin/Programming/gcc/gcc/varasm.c:2951 #6 0x000000000176d93f in const_hash_1 (exp=) at /home/marxin/Programming/gcc/gcc/varasm.c:3054 #7 0x000000000176fdc2 in lookup_constant_def (exp=) at /home/marxin/Programming/gcc/gcc/varasm.c:3557 #8 0x0000000000dd5778 in cst_pool_loc_descr (loc=) at /home/marxin/Programming/gcc/gcc/dwarf2out.c:17288 That was in situation where we emit debug info of a function that has an inlined __PRETTY_FUNCTION__ from a different function. As seen, the constant is output due to const_hash_1 function call. Proper fix would be to not emit these string constants for purpose of hash function. However, I still see some minor ICEs, it's probably related to decay_conversion in cp_fname_init: 1) ./xg++ -B. /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C:6:17: internal compiler error: Segmentation fault 6 | [] { return __func__; }(); | ^~~~~~~~ 0x1344568 crash_signal /home/marxin/Programming/gcc/gcc/toplev.c:325 0x7ffff6bc310f ??? /usr/src/debug/glibc-2.27-6.1.x86_64/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:0 0x9db134 is_capture_proxy(tree_node*) /home/marxin/Programming/gcc/gcc/cp/lambda.c:261 0xaeecb7 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) /home/marxin/Programming/gcc/gcc/cp/pt.c:16700 0xaee5fd tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) /home/marxin/Programming/gcc/gcc/cp/pt.c:16636 0xaf0ffb tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) /home/marxin/Programming/gcc/gcc/cp/pt.c:16942 where (gdb) p debug_tree(decl) unit-size align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff69b5498 precision:8 min max pointer_to_this > unsigned DI size unit-size align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff69b5540> readonly used tree_2 unsigned DI /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C:6:17 size unit-size align:64 warn_if_not_align:0 context value-expr constant arg:0 constant arg:0 constant "operator()\000">>>> and #0 0x00000000009db134 in is_capture_proxy (decl=) at /home/marxin/Programming/gcc/gcc/cp/lambda.c:261 2 ) ./xg++ -B. /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/ext/pretty2.C -c /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/ext/pretty2.C:16:24: internal compiler error: Segmentation fault 16 | __PRETTY_FUNCTION__), 0)) | ^ /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/ext/pretty2.C:36:10: note: in expansion of macro ‘assert’ 36 | int a = (assert (foo ()), 1); | ^~~~~~ 0x1344568 crash_signal /home/marxin/Programming/gcc/gcc/toplev.c:325 0x7ffff6bc310f ??? /usr/src/debug/glibc-2.27-6.1.x86_64/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:0 0x9db270 is_capture_proxy(tree_node*) /home/marxin/Programming/gcc/gcc/cp/lambda.c:265 0x9dbad9 is_normal_capture_proxy(tree_node*) /home/marxin/Programming/gcc/gcc/cp/lambda.c:274 0x9c1fe6 mark_use(tree_node*, bool, bool, unsigned int, bool) /home/marxin/Programming/gcc/gcc/cp/expr.c:114 0x89d9ab convert_like_real /home/marxin/Programming/gcc/gcc/cp/call.c:6905 where: (gdb) p debug_tree(decl) unit-size align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff69b4498 precision:8 min max pointer_to_this > unsigned type_6 DI size unit-size align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff69b4540> readonly used tree_1 tree_2 unsigned read decl_6 DI /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/ext/pretty2.C:36:10 size unit-size align:64 warn_if_not_align:0 value-expr constant arg:0 constant arg:0 constant "top level\000">>> chain > Can please a C++ maintainer help me with that? Having that I hope I can finish the patch. Thank you, Martin --------------3F506F183B3C867AD8B20530 Content-Type: text/x-patch; name="0001-Make-__PRETTY_FUNCTION__-like-functions-mergeable-st.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0001-Make-__PRETTY_FUNCTION__-like-functions-mergeable-st.pa"; filename*1="tch" Content-length: 11766 >From 19db91a83ef40cbe8ca598fb397ee9a9fd8155eb Mon Sep 17 00:00:00 2001 From: marxin Date: Thu, 4 Oct 2018 15:34:51 +0200 Subject: [PATCH] Make __PRETTY_FUNCTION__-like functions mergeable string csts (PR c++/64266). gcc/ChangeLog: 2018-10-22 Martin Liska PR c++/64266 PR bootstrap/70422 * varasm.c (decode_addr_const): Add new argument build. (const_hash_1): Set build to false by default. (lookup_constant_def): Do not build by default. gcc/cp/ChangeLog: 2018-10-22 Martin Liska PR c++/64266 PR bootstrap/70422 * decl.c (cp_fname_init): Decay the initializer to pointer. (cp_make_fname_decl): Set DECL_DECLARED_CONSTEXPR_P, DECL_VALUE_EXPR, DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P. Don't call cp_finish_decl. * pt.c (tsubst_expr): Set DECL_VALUE_EXPR, DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P. Don't call cp_finish_decl. gcc/testsuite/ChangeLog: 2018-10-22 Martin Liska PR c++/64266 PR bootstrap/70422 * g++.dg/cpp0x/constexpr-__func__2.C (main): (SA): Make it static assert. * g++.old-deja/g++.ext/pretty4.C: Remove. --- gcc/cp/decl.c | 23 +++-- gcc/cp/pt.c | 25 +++--- .../g++.dg/cpp0x/constexpr-__func__2.C | 7 +- gcc/testsuite/g++.old-deja/g++.ext/pretty4.C | 85 ------------------- gcc/varasm.c | 43 ++++++---- 5 files changed, 62 insertions(+), 121 deletions(-) delete mode 100644 gcc/testsuite/g++.old-deja/g++.ext/pretty4.C diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2d9d56ef6e1..13167582266 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4445,13 +4445,15 @@ cp_fname_init (const char* name, tree *type_p) type = cp_build_qualified_type (char_type_node, TYPE_QUAL_CONST); type = build_cplus_array_type (type, domain); - *type_p = type; + *type_p = type_decays_to (type); if (init) TREE_TYPE (init) = type; else init = error_mark_node; + init = decay_conversion (init, tf_warning_or_error); + return init; } @@ -4474,23 +4476,34 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep) if (name) free (CONST_CAST (char *, name)); - TREE_STATIC (decl) = 1; + /* As we're using pushdecl_with_scope, we must set the context. */ + DECL_CONTEXT (decl) = current_function_decl; + TREE_READONLY (decl) = 1; DECL_ARTIFICIAL (decl) = 1; + DECL_DECLARED_CONSTEXPR_P (decl) = 1; TREE_USED (decl) = 1; + if (init) + { + SET_DECL_VALUE_EXPR (decl, init); + DECL_HAS_VALUE_EXPR_P (decl) = 1; + /* For decl_constant_var_p. */ + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1; + } + if (current_function_decl) { DECL_CONTEXT (decl) = current_function_decl; decl = pushdecl_outermost_localscope (decl); - cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE, - LOOKUP_ONLYCONVERTING); + if (decl != error_mark_node) + add_decl_expr (decl); } else { DECL_THIS_STATIC (decl) = true; - pushdecl_top_level_and_finish (decl, init); + pushdecl_top_level_and_finish (decl, NULL_TREE); } return decl; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b8b6545434b..0269fa5129a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16746,6 +16746,19 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, DECL_CONTEXT (decl) = current_function_decl; cp_check_omp_declare_reduction (decl); } + else if (VAR_P (decl) + && DECL_PRETTY_FUNCTION_P (decl)) + { + /* For __PRETTY_FUNCTION__ we have to adjust the + initializer. */ + const char *const name + = cxx_printable_name (current_function_decl, 2); + init = cp_fname_init (name, &TREE_TYPE (decl)); + SET_DECL_VALUE_EXPR (decl, init); + DECL_HAS_VALUE_EXPR_P (decl) = 1; + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1; + maybe_push_decl (decl); + } else { int const_init = false; @@ -16760,17 +16773,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, complain, in_decl, &first, &cnt); - if (VAR_P (decl) - && DECL_PRETTY_FUNCTION_P (decl)) - { - /* For __PRETTY_FUNCTION__ we have to adjust the - initializer. */ - const char *const name - = cxx_printable_name (current_function_decl, 2); - init = cp_fname_init (name, &TREE_TYPE (decl)); - } - else - init = tsubst_init (init, decl, args, complain, in_decl); + init = tsubst_init (init, decl, args, complain, in_decl); if (VAR_P (decl)) const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C index e6782905423..673fb4f3a93 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C @@ -1,5 +1,5 @@ // PR c++/70353 -// { dg-do link { target c++11 } } +// { dg-do compile { target c++11 } } constexpr const char* ce () { @@ -8,6 +8,5 @@ constexpr const char* ce () const char *c = ce(); -int main() -{ -} +#define SA(X) static_assert((X),#X) +SA(ce()[0] == 'c'); diff --git a/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C b/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C deleted file mode 100644 index 9017d567132..00000000000 --- a/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C +++ /dev/null @@ -1,85 +0,0 @@ -// { dg-do run } -// Copyright (C) 2000 Free Software Foundation, Inc. -// Contributed by Nathan Sidwell 3 Mar 2000 - -// __PRETTY_FUNCTION__, __FUNCTION__ and __function__ should have the -// type char const [X], where X is the right value for that particular function - -static void const *strings[4]; -static void const *tpls[4]; -static unsigned pos = 0; -static int fail; -static void const *ptr = 0; - -void unover (char const (*)[5]) {} -void foo (char const (*)[5]) {} -void foo (void *) {fail = 1;} -void foo (void const *) {fail = 1;} -void baz (char const (&)[5]) {} - -template void PV (char const (&objRef)[I]) -{ - strings[pos] = objRef; - tpls[pos] = __PRETTY_FUNCTION__; - pos++; -} - -void fn () -{ - PV (__FUNCTION__); - PV (__func__); - PV (__PRETTY_FUNCTION__); - PV ("wibble"); -} - -void baz () -{ - ptr = __FUNCTION__; - // there should be no string const merging - if (ptr == "baz") - fail = 1; - // but all uses should be the same. - if (ptr != __FUNCTION__) - fail = 1; -} -int baz (int) -{ - return ptr == __FUNCTION__; -} - -int main () -{ - // make sure we actually emit the VAR_DECL when needed, and things have the - // expected type. - foo (&__FUNCTION__); - baz (__FUNCTION__); - unover (&__FUNCTION__); - if (fail) - return 1; - - // __FUNCTION__ should be unique across functions with the same base name - // (it's a local static, _not_ a string). - baz (); - if (fail) - return 1; - if (baz (1)) - return 1; - fn (); - - // Check the names of fn. They should all be distinct strings (though two - // will have the same value). - if (strings[0] == strings[1]) - return 1; - if (strings[0] == strings[2]) - return 1; - if (strings[1] == strings[2]) - return 1; - - // check the names of the template functions so invoked - if (tpls[0] != tpls[1]) - return 1; - if (tpls[0] == tpls[2]) - return 1; - - return 0; -} diff --git a/gcc/varasm.c b/gcc/varasm.c index c789a03e1f3..0040f07c0e4 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -105,8 +105,8 @@ static int contains_pointers_p (tree); #ifdef ASM_OUTPUT_EXTERNAL static bool incorporeal_function_p (tree); #endif -static void decode_addr_const (tree, struct addr_const *); -static hashval_t const_hash_1 (const tree); +static bool decode_addr_const (tree, struct addr_const *, bool build = true); +static hashval_t const_hash_1 (const tree, bool build = true); static int compare_constant (const tree, const tree); static void output_constant_def_contents (rtx); static void output_addressed_constants (tree); @@ -2877,15 +2877,17 @@ assemble_real (REAL_VALUE_TYPE d, scalar_float_mode mode, unsigned int align, /* Given an expression EXP with a constant value, reduce it to the sum of an assembler symbol and an integer. Store them both in the structure *VALUE. - EXP must be reducible. */ + EXP must be reducible. + If BUILD is false the function may fail if it is address expr of a constant + that is not in the constant pool. */ struct addr_const { rtx base; poly_int64 offset; }; -static void -decode_addr_const (tree exp, struct addr_const *value) +static bool +decode_addr_const (tree exp, struct addr_const *value, bool build) { tree target = TREE_OPERAND (exp, 0); poly_int64 offset = 0; @@ -2943,7 +2945,14 @@ decode_addr_const (tree exp, struct addr_const *value) case COMPLEX_CST: case CONSTRUCTOR: case INTEGER_CST: - x = output_constant_def (target, 1); + if (!build) + { + x = lookup_constant_def (target); + if (!x) + return false; + } + else + x = output_constant_def (target, 1); break; case INDIRECT_REF: @@ -2962,6 +2971,7 @@ decode_addr_const (tree exp, struct addr_const *value) value->base = x; value->offset = offset; + return true; } static GTY(()) hash_table *const_desc_htab; @@ -2985,7 +2995,7 @@ tree_descriptor_hasher::hash (constant_descriptor_tree *ptr) } static hashval_t -const_hash_1 (const tree exp) +const_hash_1 (const tree exp, bool build) { const char *p; hashval_t hi; @@ -3014,8 +3024,8 @@ const_hash_1 (const tree exp) break; case COMPLEX_CST: - return (const_hash_1 (TREE_REALPART (exp)) * 5 - + const_hash_1 (TREE_IMAGPART (exp))); + return (const_hash_1 (TREE_REALPART (exp), build) * 5 + + const_hash_1 (TREE_IMAGPART (exp), build)); case VECTOR_CST: { @@ -3023,7 +3033,7 @@ const_hash_1 (const tree exp) hi = hi * 563 + VECTOR_CST_NELTS_PER_PATTERN (exp); unsigned int count = vector_cst_encoded_nelts (exp); for (unsigned int i = 0; i < count; ++i) - hi = hi * 563 + const_hash_1 (VECTOR_CST_ENCODED_ELT (exp, i)); + hi = hi * 563 + const_hash_1 (VECTOR_CST_ENCODED_ELT (exp, i), build); return hi; } @@ -3036,7 +3046,7 @@ const_hash_1 (const tree exp) FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value) if (value) - hi = hi * 603 + const_hash_1 (value); + hi = hi * 603 + const_hash_1 (value, build); return hi; } @@ -3046,7 +3056,8 @@ const_hash_1 (const tree exp) { struct addr_const value; - decode_addr_const (exp, &value); + if (!decode_addr_const (exp, &value, build)) + return 0; switch (GET_CODE (value.base)) { case SYMBOL_REF: @@ -3072,11 +3083,11 @@ const_hash_1 (const tree exp) case PLUS_EXPR: case POINTER_PLUS_EXPR: case MINUS_EXPR: - return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9 - + const_hash_1 (TREE_OPERAND (exp, 1))); + return (const_hash_1 (TREE_OPERAND (exp, 0), build) * 9 + + const_hash_1 (TREE_OPERAND (exp, 1), build)); CASE_CONVERT: - return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2; + return const_hash_1 (TREE_OPERAND (exp, 0), build) * 7 + 2; default: /* A language specific constant. Just hash the code. */ @@ -3549,7 +3560,7 @@ lookup_constant_def (tree exp) struct constant_descriptor_tree key; key.value = exp; - key.hash = const_hash_1 (exp); + key.hash = const_hash_1 (exp, false); constant_descriptor_tree *desc = const_desc_htab->find_with_hash (&key, key.hash); -- 2.19.0 --------------3F506F183B3C867AD8B20530--