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 <mli...@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 <mli...@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 <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/cp/ChangeLog:

2018-10-31  Martin Liska  <mli...@suse.cz>
	    Jason Merrill  <ja...@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  <mli...@suse.cz>
	    Jason Merrill  <ja...@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 <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;
-}
-- 
2.19.0

Reply via email to