Make __PRETTY_FUNCTION__-like functions mergeable string csts (PR c++/64266).
authorMartin Liska <mliska@suse.cz>
Thu, 1 Nov 2018 09:19:31 +0000 (10:19 +0100)
committerMartin Liska <marxin@gcc.gnu.org>
Thu, 1 Nov 2018 09:19:31 +0000 (09:19 +0000)
2018-11-01  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.
2018-11-01  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.

Co-Authored-By: Jason Merrill <jason@redhat.com>
From-SVN: r265711

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/lambda.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C
gcc/testsuite/g++.old-deja/g++.ext/pretty4.C [deleted file]

index 8e586a1f51450e51e1542494681968a39b14973b..6d483455922714e9c11db8355b8d96c62d9c5c8f 100644 (file)
@@ -1,3 +1,16 @@
+2018-11-01  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.
+
 2018-10-31  Nathan Sidwell  <nathan@acm.org>
 
        * cp-tree.h (OVL_DEDUP_P): New.
index 03e88838cbe28c282297e87ba8767e796b425a49..42449f10a48907ffa220638a5d8027952a86a2cd 100644 (file)
@@ -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
index 11320b65e715ffcc1fe15c4f888c09bf2b122e52..1cea5262b620c73d79d4b3ac21745981ae0046bd 100644 (file)
@@ -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.  */
index 297327f1ab6bc159fa6e683b4d3a2e9cc44f19f1..318671bbcd0a209a2f9166253fd79fd40abf64dc 100644 (file)
@@ -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)));
 }
 
index fc6cf98950195af21b008ab8c654dcb79be5bd48..2dc0cb1629cdc183273fd27b1677b5beb1b4a3eb 100644 (file)
@@ -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
index 157b588863725ae8203ea1663904d694572dc152..8a0e66d4951ed34a9294779c01f98d27d516ce7e 100644 (file)
@@ -1,3 +1,14 @@
+2018-11-01  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.
+
 2018-10-31  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
        PR fortran/20520
index e6782905423b5f72747f9d5622c06db77b9b32bd..673fb4f3a93cbd83fd2c1a78d1da8fce3e71c2f3 100644 (file)
@@ -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 (file)
index 9017d56..0000000
+++ /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;
-}