diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5cb8eaa252ca..2028f7e6d631 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2016-03-28  Jason Merrill  <jason@redhat.com>
+
+	PR c++/70422
+	PR c++/64266
+	PR c++/70353
+	* decl.c, pt.c, constexpr.c: Revert last patch.
+
 2016-03-25  Jason Merrill  <jason@redhat.com>
 	    Martin Liška  <mliska@suse.cz>
 
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 7776caca4d3a..8ea71113d999 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3363,10 +3363,6 @@ 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.  */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index a88b642f8dd4..cd5db3f06dc3 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4185,15 +4185,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;
 }
 
@@ -4219,20 +4217,12 @@ 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;
@@ -4241,12 +4231,13 @@ 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);
-      add_decl_expr (decl);
+      cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
+		      LOOKUP_ONLYCONVERTING);
     }
   else
     {
       DECL_THIS_STATIC (decl) = true;
-      pushdecl_top_level_and_finish (decl, NULL_TREE);
+      pushdecl_top_level_and_finish (decl, init);
     }
 
   return decl;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e0b7a2a90aab..a6398c04f85e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15194,25 +15194,21 @@ 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);
-
-		    init = tsubst_init (init, decl, args, complain, in_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);
 
 		    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
deleted file mode 100644
index 226ae199daae..000000000000
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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
deleted file mode 100644
index cd4c014061e5..000000000000
--- a/gcc/testsuite/g++.dg/ext/fnname5.C
+++ /dev/null
@@ -1,33 +0,0 @@
-// PR c++/64266
-/* { dg-do compile } */
-
-extern "C" int printf (const char *, ...);
-
-struct A
-{
-  void foo(int i)
-  {
-    printf ("__FUNCTION__ = %s\n", __FUNCTION__);
-    printf ("__PRETTY_FUNCTION__ = %s\n", __PRETTY_FUNCTION__);
-  }
-
-  void foo()
-  {
-     printf ("__FUNCTION__ = %s\n", __FUNCTION__);
-  }
-};
-
-int
-main ()
-{
-  A a;
-  a.foo (0);
-  a.foo ();
-  return 0;
-}
-
-/* { dg-final { scan-assembler-not "_ZZN1A3fooEvE12__FUNCTION__" } } */
-/* { dg-final { scan-assembler-not "_ZZN1A3fooEiE12__FUNCTION__" } } */
-/* { dg-final { scan-assembler-not "_ZZN1A3fooEiE19__PRETTY_FUNCTION__" } } */
-/* { dg-final { scan-assembler ".(string|ascii) \"void A::foo\\(int\\)(.0)?\"" } } */
-/* { dg-final { scan-assembler ".(string|ascii) \"foo(.0)?\"" } } */
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 000000000000..9017d5671324
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C
@@ -0,0 +1,85 @@
+// { 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;
+}