Make __PRETTY_FUNCTION__-like functions mergeable string csts (PR c++/64266).

Message ID 7b6f3ceb-d303-4b45-5740-0f4a0f3059cf@suse.cz
State New
Headers show
Series
  • Make __PRETTY_FUNCTION__-like functions mergeable string csts (PR c++/64266).
Related show

Commit Message

Martin Liška Oct. 23, 2018, 8:59 a.m.
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

Comments

Richard Biener Oct. 23, 2018, 11:19 a.m. | #1
On Tue, Oct 23, 2018 at 10:59 AM Martin Liška <mliska@suse.cz> wrote:
>

> 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.


possibly sth like the following - that avoids all cases of calling
output_constant_def.  Probably worth testing
separately.

diff --git a/gcc/varasm.c b/gcc/varasm.c
index 91650eea9f7..9121dbd2c84 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -3047,6 +3047,10 @@ const_hash_1 (const tree exp)
       }

     case ADDR_EXPR:
+      if (CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))
+       return const_hash_1 (TREE_OPERAND (exp, 0));
+
+      /* Fallthru.  */
     case FDESC_EXPR:
       {
        struct addr_const value;

> 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
Martin Liška Oct. 24, 2018, 1:34 p.m. | #2
On 10/23/18 1:19 PM, Richard Biener wrote:
> On Tue, Oct 23, 2018 at 10:59 AM Martin Liška <mliska@suse.cz> wrote:

>>

>> 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.

> 

> possibly sth like the following - that avoids all cases of calling

> output_constant_def.  Probably worth testing

> separately.


Thanks for the hint. I can confirm it works for the pretty function patch.
I also tested the patch separately on current trunk. May I install the hunk
right now, or should I wait?

Thanks,
Martin

> 

> diff --git a/gcc/varasm.c b/gcc/varasm.c

> index 91650eea9f7..9121dbd2c84 100644

> --- a/gcc/varasm.c

> +++ b/gcc/varasm.c

> @@ -3047,6 +3047,10 @@ const_hash_1 (const tree exp)

>        }

> 

>      case ADDR_EXPR:

> +      if (CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))

> +       return const_hash_1 (TREE_OPERAND (exp, 0));

> +

> +      /* Fallthru.  */

>      case FDESC_EXPR:

>        {

>         struct addr_const value;

> 

>> 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
Richard Biener Oct. 24, 2018, 1:37 p.m. | #3
On Wed, Oct 24, 2018 at 3:34 PM Martin Liška <mliska@suse.cz> wrote:
>

> On 10/23/18 1:19 PM, Richard Biener wrote:

> > On Tue, Oct 23, 2018 at 10:59 AM Martin Liška <mliska@suse.cz> wrote:

> >>

> >> 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.

> >

> > possibly sth like the following - that avoids all cases of calling

> > output_constant_def.  Probably worth testing

> > separately.

>

> Thanks for the hint. I can confirm it works for the pretty function patch.

> I also tested the patch separately on current trunk. May I install the hunk

> right now, or should I wait?


You can install it right now I think.

Richard.

> Thanks,

> Martin

>

> >

> > diff --git a/gcc/varasm.c b/gcc/varasm.c

> > index 91650eea9f7..9121dbd2c84 100644

> > --- a/gcc/varasm.c

> > +++ b/gcc/varasm.c

> > @@ -3047,6 +3047,10 @@ const_hash_1 (const tree exp)

> >        }

> >

> >      case ADDR_EXPR:

> > +      if (CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))

> > +       return const_hash_1 (TREE_OPERAND (exp, 0));

> > +

> > +      /* Fallthru.  */

> >      case FDESC_EXPR:

> >        {

> >         struct addr_const value;

> >

> >> 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

>
Jason Merrill Oct. 24, 2018, 5:24 p.m. | #4
On Tue, Oct 23, 2018 at 4:59 AM Martin Liška <mliska@suse.cz> wrote:
> 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*)


The problem in both tests is that is_capture_proxy thinks your
__func__ VAR_DECL with DECL_VALUE_EXPR is a capture proxy, since it is
neither an anonymous union proxy nor a structured binding.

The standard says,

The function-local predefined variable __func__ is defined as if a
definition of the form
   static const char __func__[] = "function-name ";
had been provided, where function-name is an implementation-defined
string. It is unspecified whether such a variable has an address
distinct from that of any other object in the program.

So changing the type of __func__ (from array to pointer) still breaks
conformance.  And we need to keep the type checks from pretty4.C, even
though the checks for strings being distinct need to go.

Jason
Martin Liška Oct. 26, 2018, 7:14 a.m. | #5
On 10/24/18 7:24 PM, Jason Merrill wrote:
> On Tue, Oct 23, 2018 at 4:59 AM Martin Liška <mliska@suse.cz> wrote:

>> 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*)


Hi.

> 

> The problem in both tests is that is_capture_proxy thinks your

> __func__ VAR_DECL with DECL_VALUE_EXPR is a capture proxy, since it is

> neither an anonymous union proxy nor a structured binding.


I see, however I'm a rookie in area of C++ FE. Would it be solvable this problem
with lambdas?

> 

> The standard says,

> 

> The function-local predefined variable __func__ is defined as if a

> definition of the form

>    static const char __func__[] = "function-name ";

> had been provided, where function-name is an implementation-defined

> string. It is unspecified whether such a variable has an address

> distinct from that of any other object in the program.

> 

> So changing the type of __func__ (from array to pointer) still breaks

> conformance.  And we need to keep the type checks from pretty4.C, even

> though the checks for strings being distinct need to go.


I added following patch which puts back type to const char[] (instead of char *)
and I made the variable static. Now I see pretty4.C testcase passing again.
To be honest I'm not convinced about the FE changes, so a help would
be appreciated.

Thanks,
Martin

> 

> Jason

>
From fd2e13b23e0bbbb7a7b02025432843782e1ab579 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>

Date: Thu, 25 Oct 2018 18:12:10 +0200
Subject: [PATCH] Fix back.

---
 gcc/cp/decl.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9624df081e4..74ad871b3f4 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4445,15 +4445,13 @@ 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_decays_to (type);
+  *type_p = type;
 
   if (init)
     TREE_TYPE (init) = type;
   else
     init = error_mark_node;
 
-  init = decay_conversion (init, tf_warning_or_error);
-
   return init;
 }
 
@@ -4482,6 +4480,7 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep)
   TREE_READONLY (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   DECL_DECLARED_CONSTEXPR_P (decl) = 1;
+  TREE_STATIC (decl) = 1;
 
   TREE_USED (decl) = 1;
 
-- 
2.19.0
Jason Merrill Oct. 29, 2018, 1:37 p.m. | #6
On Fri, Oct 26, 2018 at 3:14 AM Martin Liška <mliska@suse.cz> wrote:
> On 10/24/18 7:24 PM, Jason Merrill wrote:

> > On Tue, Oct 23, 2018 at 4:59 AM Martin Liška <mliska@suse.cz> wrote:

> >> 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*)

>

> Hi.

>

> >

> > The problem in both tests is that is_capture_proxy thinks your

> > __func__ VAR_DECL with DECL_VALUE_EXPR is a capture proxy, since it is

> > neither an anonymous union proxy nor a structured binding.

>

> I see, however I'm a rookie in area of C++ FE. Would it be solvable this problem

> with lambdas?

>

> >

> > The standard says,

> >

> > The function-local predefined variable __func__ is defined as if a

> > definition of the form

> >    static const char __func__[] = "function-name ";

> > had been provided, where function-name is an implementation-defined

> > string. It is unspecified whether such a variable has an address

> > distinct from that of any other object in the program.

> >

> > So changing the type of __func__ (from array to pointer) still breaks

> > conformance.  And we need to keep the type checks from pretty4.C, even

> > though the checks for strings being distinct need to go.

>

> I added following patch which puts back type to const char[] (instead of char *)

> and I made the variable static. Now I see pretty4.C testcase passing again.

> To be honest I'm not convinced about the FE changes, so a help would

> be appreciated.


OK, I'll poke at it.

Jason
Jason Merrill Oct. 31, 2018, 1:42 a.m. | #7
On 10/29/18 9:37 AM, Jason Merrill wrote:
> On Fri, Oct 26, 2018 at 3:14 AM Martin Liška <mliska@suse.cz> wrote:

>> On 10/24/18 7:24 PM, Jason Merrill wrote:

>>> On Tue, Oct 23, 2018 at 4:59 AM Martin Liška <mliska@suse.cz> wrote:

>>>> 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*)

>>

>> Hi.

>>

>>>

>>> The problem in both tests is that is_capture_proxy thinks your

>>> __func__ VAR_DECL with DECL_VALUE_EXPR is a capture proxy, since it is

>>> neither an anonymous union proxy nor a structured binding.

>>

>> I see, however I'm a rookie in area of C++ FE. Would it be solvable this problem

>> with lambdas?

>>

>>>

>>> The standard says,

>>>

>>> The function-local predefined variable __func__ is defined as if a

>>> definition of the form

>>>     static const char __func__[] = "function-name ";

>>> had been provided, where function-name is an implementation-defined

>>> string. It is unspecified whether such a variable has an address

>>> distinct from that of any other object in the program.

>>>

>>> So changing the type of __func__ (from array to pointer) still breaks

>>> conformance.  And we need to keep the type checks from pretty4.C, even

>>> though the checks for strings being distinct need to go.

>>

>> I added following patch which puts back type to const char[] (instead of char *)

>> and I made the variable static. Now I see pretty4.C testcase passing again.

>> To be honest I'm not convinced about the FE changes, so a help would

>> be appreciated.

> 

> OK, I'll poke at it.


This further patch teaches is_capture_proxy about function-name 
variables, and changes the handling of __PRETTY_FUNCTION__ in template 
instantiations to create new variables rather than instantiations.

The C++ changes are OK with this.
commit 100f6f38f9d8bbb5d77ba7a4ccb86a4c85aa2cd9
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Oct 29 22:35:59 2018 -0400

    fname-p

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8454cb4e178..f1a10297e79 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3122,6 +3122,14 @@ struct GTY(()) lang_decl {
   (DECL_NAME (NODE) \
    && id_equal (DECL_NAME (NODE), "__PRETTY_FUNCTION__"))
 
+/* For a DECL, true if it is __func__ or similar.  */
+#define DECL_FNAME_P(NODE)					\
+  (VAR_P (NODE) && DECL_NAME (NODE) && DECL_ARTIFICIAL (NODE)	\
+   && DECL_HAS_VALUE_EXPR_P (NODE)				\
+   && (id_equal (DECL_NAME (NODE), "__PRETTY_FUNCTION__")	\
+       || id_equal (DECL_NAME (NODE), "__FUNCTION__")		\
+       || id_equal (DECL_NAME (NODE), "__func__")))
+
 /* Nonzero if the variable was declared to be thread-local.
    We need a special C++ version of this test because the middle-end
    DECL_THREAD_LOCAL_P uses the symtab, so we can't use it for
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index cce9cc99ff1..bde8023ce3b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4465,7 +4465,7 @@ cp_fname_init (const char* name, tree *type_p)
 static tree
 cp_make_fname_decl (location_t loc, tree id, int type_dep)
 {
-  const char *const name = (type_dep && processing_template_decl
+  const char *const name = (type_dep && in_template_function ()
 			    ? NULL : fname_as_string (type_dep));
   tree type;
   tree init = cp_fname_init (name, &type);
@@ -7064,8 +7064,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 	    init = NULL_TREE;
 	  release_tree_vector (cleanups);
 	}
-      else if (!DECL_PRETTY_FUNCTION_P (decl))
+      else
 	{
+	  gcc_assert (!DECL_PRETTY_FUNCTION_P (decl));
 	  /* Deduce array size even if the initializer is dependent.  */
 	  maybe_deduce_size_from_array_init (decl, init);
 	  /* And complain about multiple initializers.  */
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 297327f1ab6..318671bbcd0 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -262,6 +262,7 @@ is_capture_proxy (tree decl)
 	  && DECL_HAS_VALUE_EXPR_P (decl)
 	  && !DECL_ANON_UNION_VAR_P (decl)
 	  && !DECL_DECOMPOSITION_P (decl)
+	  && !DECL_FNAME_P (decl)
 	  && LAMBDA_FUNCTION_P (DECL_CONTEXT (decl)));
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6975027076e..510264d38a0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16702,6 +16702,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 	    register_local_specialization (inst, decl);
 	    break;
 	  }
+	else if (DECL_PRETTY_FUNCTION_P (decl))
+	  decl = make_fname_decl (DECL_SOURCE_LOCATION (decl),
+				  DECL_NAME (decl),
+				  true/*DECL_PRETTY_FUNCTION_P (decl)*/);
 	else if (DECL_IMPLICIT_TYPEDEF_P (decl)
 		 && LAMBDA_TYPE_P (TREE_TYPE (decl)))
 	  /* Don't copy the old closure; we'll create a new one in
@@ -16746,19 +16750,6 @@ 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;
diff --git a/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C b/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C
new file mode 100644
index 00000000000..eb5d0de5cc6
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C
@@ -0,0 +1,39 @@
+// { dg-do run  }
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 3 Mar 2000 <nathan@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 int fail;
+
+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]) {}
+
+void baz ()
+{
+  static void const *ptr = __FUNCTION__;
+  // all uses should be the same.
+  if (ptr != __FUNCTION__)
+    fail = 1;
+}
+
+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;
+  
+  baz ();
+  if (fail)
+    return 1;
+  
+  return 0;
+}
Martin Liška Nov. 1, 2018, 9:16 a.m. | #8
On 10/31/18 2:42 AM, Jason Merrill wrote:
> On 10/29/18 9:37 AM, Jason Merrill wrote:

>> On Fri, Oct 26, 2018 at 3:14 AM Martin Liška <mliska@suse.cz> wrote:

>>> On 10/24/18 7:24 PM, Jason Merrill wrote:

>>>> On Tue, Oct 23, 2018 at 4:59 AM Martin Liška <mliska@suse.cz> wrote:

>>>>> 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*)

>>>

>>> Hi.

>>>

>>>>

>>>> The problem in both tests is that is_capture_proxy thinks your

>>>> __func__ VAR_DECL with DECL_VALUE_EXPR is a capture proxy, since it is

>>>> neither an anonymous union proxy nor a structured binding.

>>>

>>> I see, however I'm a rookie in area of C++ FE. Would it be solvable this problem

>>> with lambdas?

>>>

>>>>

>>>> The standard says,

>>>>

>>>> The function-local predefined variable __func__ is defined as if a

>>>> definition of the form

>>>>     static const char __func__[] = "function-name ";

>>>> had been provided, where function-name is an implementation-defined

>>>> string. It is unspecified whether such a variable has an address

>>>> distinct from that of any other object in the program.

>>>>

>>>> So changing the type of __func__ (from array to pointer) still breaks

>>>> conformance.  And we need to keep the type checks from pretty4.C, even

>>>> though the checks for strings being distinct need to go.

>>>

>>> I added following patch which puts back type to const char[] (instead of char *)

>>> and I made the variable static. Now I see pretty4.C testcase passing again.

>>> To be honest I'm not convinced about the FE changes, so a help would

>>> be appreciated.

>>

>> OK, I'll poke at it.

> 

> This further patch teaches is_capture_proxy about function-name variables, and changes the handling of __PRETTY_FUNCTION__ in template instantiations to create new variables rather than instantiations.

> 

> The C++ changes are OK with this.

> 


Thank you very much Jason!
There's final version of the patch that I'm going to install.

Martin
From 077608ee88e277d569851969babe0f2fcf20fbf2 Mon Sep 17 00:00:00 2001
From: marxin <mliska@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/cp/ChangeLog:

2018-10-31  Martin Liska  <mliska@suse.cz>
	    Jason Merrill  <jason@redhat.com>

	PR c++/64266
	PR bootstrap/70422
	PR ipa/81277
	* cp-tree.h (DECL_FNAME_P): New macro.
	* decl.c (cp_make_fname_decl): Set DECL_DECLARED_CONSTEXPR_P,
        DECL_VALUE_EXPR, DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.
	(cp_finish_decl):
	* lambda.c (is_capture_proxy): Use DECL_FNAME_P.
	* pt.c (tsubst_expr): Handle DECL_PRETTY_FUNCTION_P.

gcc/testsuite/ChangeLog:

2018-10-31  Martin Liska  <mliska@suse.cz>
	    Jason Merrill  <jason@redhat.com>

	PR c++/64266
	PR bootstrap/70422
	PR ipa/81277
	* g++.dg/cpp0x/constexpr-__func__2.C: Make it a compilation
	test.
	* g++.old-deja/g++.ext/pretty4.C: Remove as the run-time
	assumptions are not longer valid.
---
 gcc/cp/cp-tree.h                              |  8 ++
 gcc/cp/decl.c                                 | 25 ++++--
 gcc/cp/lambda.c                               |  1 +
 gcc/cp/pt.c                                   | 16 ++--
 .../g++.dg/cpp0x/constexpr-__func__2.C        |  7 +-
 gcc/testsuite/g++.old-deja/g++.ext/pretty4.C  | 85 -------------------
 6 files changed, 36 insertions(+), 106 deletions(-)
 delete mode 100644 gcc/testsuite/g++.old-deja/g++.ext/pretty4.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 03e88838cbe..42449f10a48 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3132,6 +3132,14 @@ struct GTY(()) lang_decl {
   (DECL_NAME (NODE) \
    && id_equal (DECL_NAME (NODE), "__PRETTY_FUNCTION__"))
 
+/* For a DECL, true if it is __func__ or similar.  */
+#define DECL_FNAME_P(NODE)					\
+  (VAR_P (NODE) && DECL_NAME (NODE) && DECL_ARTIFICIAL (NODE)	\
+   && DECL_HAS_VALUE_EXPR_P (NODE)				\
+   && (id_equal (DECL_NAME (NODE), "__PRETTY_FUNCTION__")	\
+       || id_equal (DECL_NAME (NODE), "__FUNCTION__")		\
+       || id_equal (DECL_NAME (NODE), "__func__")))
+
 /* Nonzero if the variable was declared to be thread-local.
    We need a special C++ version of this test because the middle-end
    DECL_THREAD_LOCAL_P uses the symtab, so we can't use it for
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 11320b65e71..1cea5262b62 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4465,7 +4465,7 @@ cp_fname_init (const char* name, tree *type_p)
 static tree
 cp_make_fname_decl (location_t loc, tree id, int type_dep)
 {
-  const char *const name = (type_dep && processing_template_decl
+  const char *const name = (type_dep && in_template_function ()
 			    ? NULL : fname_as_string (type_dep));
   tree type;
   tree init = cp_fname_init (name, &type);
@@ -4474,23 +4474,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_DECLARED_CONSTEXPR_P (decl) = 1;
+  TREE_STATIC (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;
@@ -7052,8 +7064,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 	    init = NULL_TREE;
 	  release_tree_vector (cleanups);
 	}
-      else if (!DECL_PRETTY_FUNCTION_P (decl))
+      else
 	{
+	  gcc_assert (!DECL_PRETTY_FUNCTION_P (decl));
 	  /* Deduce array size even if the initializer is dependent.  */
 	  maybe_deduce_size_from_array_init (decl, init);
 	  /* And complain about multiple initializers.  */
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 297327f1ab6..318671bbcd0 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -262,6 +262,7 @@ is_capture_proxy (tree decl)
 	  && DECL_HAS_VALUE_EXPR_P (decl)
 	  && !DECL_ANON_UNION_VAR_P (decl)
 	  && !DECL_DECOMPOSITION_P (decl)
+	  && !DECL_FNAME_P (decl)
 	  && LAMBDA_FUNCTION_P (DECL_CONTEXT (decl)));
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index fc6cf989501..2dc0cb1629c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16735,6 +16735,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 	    register_local_specialization (inst, decl);
 	    break;
 	  }
+	else if (DECL_PRETTY_FUNCTION_P (decl))
+	  decl = make_fname_decl (DECL_SOURCE_LOCATION (decl),
+				  DECL_NAME (decl),
+				  true/*DECL_PRETTY_FUNCTION_P (decl)*/);
 	else if (DECL_IMPLICIT_TYPEDEF_P (decl)
 		 && LAMBDA_TYPE_P (TREE_TYPE (decl)))
 	  /* Don't copy the old closure; we'll create a new one in
@@ -16793,17 +16797,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 <nathan@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;
-}
-- 
2.19.0

Patch

From 19db91a83ef40cbe8ca598fb397ee9a9fd8155eb Mon Sep 17 00:00:00 2001
From: marxin <mliska@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  <mliska@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  <mliska@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  <mliska@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 <nathan@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