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=<string_cst 0x7ffff67be210>, align=64, flags=0) at /home/marxin/Programming/gcc/gcc/varasm.c:808 #1 0x0000000001779bf3 in default_elf_select_section (decl=<string_cst 0x7ffff67be210>, reloc=0, align=64) at /home/marxin/Programming/gcc/gcc/varasm.c:6739 #2 0x000000000176efb6 in get_constant_section (exp=<string_cst 0x7ffff67be210>, align=64) at /home/marxin/Programming/gcc/gcc/varasm.c:3302 #3 0x000000000176f468 in build_constant_desc (exp=<string_cst 0x7ffff67be210>) at /home/marxin/Programming/gcc/gcc/varasm.c:3371 #4 0x000000000176f81c in output_constant_def (exp=<string_cst 0x7ffff67be210>, defer=1) at /home/marxin/Programming/gcc/gcc/varasm.c:3434 #5 0x000000000176d406 in decode_addr_const (exp=<addr_expr 0x7ffff682f8c0>, value=0x7fffffffc540) at /home/marxin/Programming/gcc/gcc/varasm.c:2951 #6 0x000000000176d93f in const_hash_1 (exp=<addr_expr 0x7ffff682f8c0>) at /home/marxin/Programming/gcc/gcc/varasm.c:3054 #7 0x000000000176fdc2 in lookup_constant_def (exp=<addr_expr 0x7ffff682f8c0>) at /home/marxin/Programming/gcc/gcc/varasm.c:3557 #8 0x0000000000dd5778 in cst_pool_loc_descr (loc=<addr_expr 0x7ffff682f8c0>) 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) <var_decl 0x7ffff7fee480 __func__ type <pointer_type 0x7ffff69b5540 type <integer_type 0x7ffff69b5498 char readonly unsigned string-flag type_6 QI size <integer_cst 0x7ffff698df78 constant 8> unit-size <integer_cst 0x7ffff698df90 constant 1> align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff69b5498 precision:8 min <integer_cst 0x7ffff698dfd8 0> max <integer_cst 0x7ffff698dfc0 255> pointer_to_this <pointer_type 0x7ffff69b5540>> unsigned DI size <integer_cst 0x7ffff698de88 constant 64> unit-size <integer_cst 0x7ffff698dea0 constant 8> 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 <integer_cst 0x7ffff698de88 64> unit-size <integer_cst 0x7ffff698dea0 8> align:64 warn_if_not_align:0 context <function_decl 0x7ffff67abd00 operator()> value-expr <nop_expr 0x7ffff67b7660 type <pointer_type 0x7ffff69b5540> constant arg:0 <addr_expr 0x7ffff67b7640 type <pointer_type 0x7ffff67bd3f0> constant arg:0 <string_cst 0x7ffff67b7620 type <array_type 0x7ffff67bd348> constant "operator()\000">>>> and #0 0x00000000009db134 in is_capture_proxy (decl=<tree 0x0>) 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) <var_decl 0x7ffff7fee870 __PRETTY_FUNCTION__ type <pointer_type 0x7ffff69b4540 type <integer_type 0x7ffff69b4498 char readonly unsigned string-flag type_6 QI size <integer_cst 0x7ffff698df78 constant 8> unit-size <integer_cst 0x7ffff698df90 constant 1> align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff69b4498 precision:8 min <integer_cst 0x7ffff698dfd8 0> max <integer_cst 0x7ffff698dfc0 255> pointer_to_this <pointer_type 0x7ffff69b4540>> unsigned type_6 DI size <integer_cst 0x7ffff698de88 constant 64> unit-size <integer_cst 0x7ffff698dea0 constant 8> 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 <integer_cst 0x7ffff698de88 64> unit-size <integer_cst 0x7ffff698dea0 8> align:64 warn_if_not_align:0 value-expr <nop_expr 0x7ffff67b69a0 type <pointer_type 0x7ffff69b4540> constant arg:0 <addr_expr 0x7ffff67b6980 type <pointer_type 0x7ffff67c3738> constant arg:0 <string_cst 0x7ffff67b6960 type <array_type 0x7ffff67c3690> constant "top level\000">>> chain <var_decl 0x7ffff7fee7e0 a>> Can please a C++ maintainer help me with that? Having that I hope I can finish the patch. Thank you, Martin
>From 19db91a83ef40cbe8ca598fb397ee9a9fd8155eb Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> 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 <mli...@suse.cz> 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 <mli...@suse.cz> 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 <mli...@suse.cz> 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 <nat...@codesourcery.com> - -// __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<unsigned I> 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<tree_descriptor_hasher> *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