re PR c++/64266 (Can GCC produce local mergeable symbols for *.__FUNCTION__ and ...
authorJason Merrill <jason@redhat.com>
Fri, 25 Mar 2016 21:29:26 +0000 (17:29 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 25 Mar 2016 21:29:26 +0000 (17:29 -0400)
PR c++/64266
PR c++/70353
Core issue 1962
* 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) [DECL_EXPR]: Set DECL_VALUE_EXPR,
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.  Don't call cp_finish_decl.
* constexpr.c (cxx_eval_constant_expression) [VAR_DECL]:
Handle DECL_VALUE_EXPR.

Co-Authored-By: Martin Liska <mliska@suse.cz>
From-SVN: r234484

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/fnname5.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.ext/pretty4.C [deleted file]

index 45450ec2f06e68b7b8947573b5e223ab722a9712..5cb8eaa252ca9dc164ed119647da11df23ed30ba 100644 (file)
@@ -1,3 +1,18 @@
+2016-03-25  Jason Merrill  <jason@redhat.com>
+           Martin Liška  <mliska@suse.cz>
+
+       PR c++/64266
+       PR c++/70353
+       Core issue 1962
+       * 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) [DECL_EXPR]: Set DECL_VALUE_EXPR,
+       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.  Don't call cp_finish_decl.
+       * constexpr.c (cxx_eval_constant_expression) [VAR_DECL]:
+       Handle DECL_VALUE_EXPR.
+
 2016-03-24  Jason Merrill  <jason@redhat.com>
 
        PR c++/70386
index 8ea71113d9991ec10e41187749dcf5c2561ee350..7776caca4d3af2fd93dbc03a44bb16955435d899 100644 (file)
@@ -3363,6 +3363,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       return (*ctx->values->get (t));
 
     case VAR_DECL:
+      if (DECL_HAS_VALUE_EXPR_P (t))
+       return cxx_eval_constant_expression (ctx, DECL_VALUE_EXPR (t), lval,
+                                            non_constant_p, overflow_p);
+      /* Fall through.  */
     case CONST_DECL:
       /* We used to not check lval for CONST_DECL, but darwin.c uses
         CONST_DECL for aggregate constants.  */
index cd5db3f06dc306758bec05471abbe41f4c240c5f..a88b642f8dd42a34d4bb173fc0117008251c5f5b 100644 (file)
@@ -4185,13 +4185,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;
 }
 
@@ -4217,12 +4219,20 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep)
   /* As we're using pushdecl_with_scope, we must set the context.  */
   DECL_CONTEXT (decl) = current_function_decl;
 
-  TREE_STATIC (decl) = 1;
   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)
     {
       cp_binding_level *b = current_binding_level;
@@ -4231,13 +4241,12 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep)
       while (b->level_chain->kind != sk_function_parms)
        b = b->level_chain;
       pushdecl_with_scope (decl, b, /*is_friend=*/false);
-      cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
-                     LOOKUP_ONLYCONVERTING);
+      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;
index a6398c04f85e0cdf9e187be6554276402d222c2e..e0b7a2a90aabcde22e111c69264a5ae64e668831 100644 (file)
@@ -15194,21 +15194,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
new file mode 100644 (file)
index 0000000..226ae19
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/70353
+// { dg-do compile { target c++11 } }
+
+constexpr const char* ce ()
+{
+   return __func__;
+}
+
+#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 (file)
index 0000000..a2ead1d
--- /dev/null
@@ -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        \"void A::foo\\(int\\)\"" } } */
+/* { dg-final { scan-assembler ".string        \"foo\"" } } */
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;
-}