On 05/01/2017 09:13 PM, Jason Merrill wrote: > On Wed, Apr 26, 2017 at 6:58 AM, Martin Liška <mli...@suse.cz> wrote: >> On 04/25/2017 01:58 PM, Jakub Jelinek wrote: >>> On Tue, Apr 25, 2017 at 01:48:05PM +0200, Martin Liška wrote: >>>> Hello. >>>> >>>> This is patch that was originally installed by Jason and later reverted >>>> due to PR70422. >>>> In the later PR Richi suggested a fix for that and Segher verified that it >>>> helped him >>>> to survive regression tests. That's reason why I'm resending that. >>>> >>>> Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. >>>> >>>> Ready to be installed? >>>> Martin >>> >>>> >From a34ce0ef37ae00609c9f3ff98a9cb0b7db6a8bd0 Mon Sep 17 00:00:00 2001 >>>> From: marxin <mli...@suse.cz> >>>> Date: Thu, 20 Apr 2017 14:56:30 +0200 >>>> Subject: [PATCH] Make __FUNCTION__ a mergeable string and do not generate >>>> symbol entry. >>>> >>>> gcc/cp/ChangeLog: >>>> >>>> 2017-04-20 Jason Merrill <ja...@redhat.com> >>>> Martin Liska <mli...@suse.cz> >>>> Segher Boessenkool <seg...@kernel.crashing.org> >>>> >>>> PR c++/64266 >>>> PR c++/70353 >>>> PR bootstrap/70422 >>>> Core issue 1962 >>>> * decl.c (cp_fname_init): Decay the initializer to pointer. >>>> (cp_make_fname_decl): Set DECL_DECLARED_CONSTEXPR_P, >>>> * pt.c (tsubst_expr) [DECL_EXPR]: Set DECL_VALUE_EXPR, >>>> DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P and >>>> DECL_IGNORED_P. Don't call cp_finish_decl. >>> >>> If we don't emit those into the debug info, will the debugger be >>> able to handle __FUNCTION__ etc. properly? >> >> No, debugger with the patch can't handled these. Similar to how clang >> behaves currently. Maybe it can be conditionally enabled with -g3, or -g? >> >>> Admittedly, right now we emit it into debug info only if those decls >>> are actually used, say on: >>> const char * foo () { return __FUNCTION__; } >>> const char * bar () { return ""; } >>> we'd emit foo::__FUNCTION__, but not bar::__FUNCTION__, so the debugger >>> has to have some handling of it anyway. But while in functions >>> that don't refer to __FUNCTION__ it is always the debugger that needs >>> to synthetize those and thus they will be always pointer-equal, >>> if there are some uses of it and for other uses the debugger would >>> synthetize it, there is the possibility that the debugger synthetized >>> string will not be the same object as actually used in the function. >> >> You're right, currently one has to use a special function to be able to >> print it in debugger. I believe we've already discussed that, according >> to spec, the strings don't have to point to a same string. >> >> Suggestions what we should do with the patch? > > We need to emit debug information for these variables. From Jim's > description in 70422 it seems that the problem is that the reference > to the string from the debug information is breaking > function_mergeable_rodata_prefix, which relies on > current_function_decl. It seems to me that its callers should pass > along their decl parameter so that f_m_r_p can use the decl's > DECL_CONTEXT rather than rely on current_function_decl being set > properly> > Jason >
Ok, after some time I returned back to it. I followed your advises and changed the function function_mergeable_rodata_prefix. Apart from a small rebase was needed. May I ask Jim to test the patch? Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. Martin
>From 8a7a8b421d81c47cf686175f309f79c0b7a8ce76 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Thu, 20 Apr 2017 14:56:30 +0200 Subject: [PATCH] Make __FUNCTION__ a mergeable string and do not generate symbol entry. gcc/cp/ChangeLog: 2017-04-20 Jason Merrill <ja...@redhat.com> Martin Liska <mli...@suse.cz> Segher Boessenkool <seg...@kernel.crashing.org> PR c++/64266 PR c++/70353 PR bootstrap/70422 Core issue 1962 * decl.c (cp_fname_init): Decay the initializer to pointer. (cp_make_fname_decl): Set DECL_DECLARED_CONSTEXPR_P, * pt.c (tsubst_expr) [DECL_EXPR]: Set DECL_VALUE_EXPR, DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P and DECL_IGNORED_P. Don't call cp_finish_decl. * decl.c (cp_make_fname_decl): Add only non error mark expression. gcc/testsuite/ChangeLog: 2017-04-20 Jason Merrill <ja...@redhat.com> Segher Boessenkool <seg...@kernel.crashing.org> PR c++/64266 PR c++/70353 PR bootstrap/70422 Core issue 1962 * g++.dg/cpp0x/constexpr-__func__2.C: Add static assert test. * g++.dg/ext/fnname5.C: New test. * g++.old-deja/g++.ext/pretty4.C: Remove. gcc/ChangeLog: 2017-07-14 Martin Liska <mli...@suse.cz> * varasm.c (function_mergeable_rodata_prefix): Use DECL_CONTEXT for function declarations. --- gcc/cp/decl.c | 24 +++++-- gcc/cp/pt.c | 26 +++++--- gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C | 7 +- gcc/testsuite/g++.dg/ext/fnname5.C | 33 +++++++++ gcc/testsuite/g++.old-deja/g++.ext/pretty4.C | 85 ------------------------ gcc/varasm.c | 7 +- 6 files changed, 76 insertions(+), 106 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/fnname5.C 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 5b8e6a22b01..3f27b72052a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4294,13 +4294,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; } @@ -4323,23 +4325,35 @@ 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_IGNORED_P (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 bd02951cb85..f8e096b9b52 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -15862,21 +15862,25 @@ 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; maybe_push_decl (decl); - 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++.dg/ext/fnname5.C b/gcc/testsuite/g++.dg/ext/fnname5.C new file mode 100644 index 00000000000..04fa7d3f92d --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/fnname5.C @@ -0,0 +1,33 @@ +// PR c++/64266 +/* { dg-do compile } */ + +extern "C" int printf (const char *, ...); + +struct A +{ + void foo(int i) + { + printf ("__FUNCTION__ = %s\n", __FUNCTION__); + printf ("__PRETTY_FUNCTION__ = %s\n", __PRETTY_FUNCTION__); + } + + void foo() + { + printf ("__FUNCTION__ = %s\n", __FUNCTION__); + } +}; + +int +main () +{ + A a; + a.foo (0); + a.foo (); + return 0; +} + +/* { dg-final { scan-assembler-not "_ZZN1A3fooEvE12__FUNCTION__" } } */ +/* { dg-final { scan-assembler-not "_ZZN1A3fooEiE12__FUNCTION__" } } */ +/* { dg-final { scan-assembler-not "_ZZN1A3fooEiE19__PRETTY_FUNCTION__" } } */ +/* { dg-final { scan-assembler ".(string|ascii)\\s+\"void A::foo\\(int\\)(.0)?\"" } } */ +/* { dg-final { scan-assembler ".(string|ascii)\\s+\"foo(.0)?\"" } } */ 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 fbaebc1b5c0..0b56898d8f3 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -760,7 +760,12 @@ default_no_function_rodata_section (tree decl ATTRIBUTE_UNUSED) static const char * function_mergeable_rodata_prefix (void) { - section *s = targetm.asm_out.function_rodata_section (current_function_decl); + tree decl = current_function_decl; + if (decl && DECL_CONTEXT (decl) + && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL) + decl = DECL_CONTEXT (decl); + + section *s = targetm.asm_out.function_rodata_section (decl); if (SECTION_STYLE (s) == SECTION_NAMED) return s->named.name; else -- 2.13.2