diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6f34380bb86..e6cb2891a6e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
 2008-12-31  Jakub Jelinek  <jakub@redhat.com>
 
+	PR c++/38647
+	* parser.c (cp_parser_primary_expression) <case RID_FUNCTION_NAME>:
+	Return error_mark_node if cp_parser_non_integral_constant_expression
+	returns true.
+
 	PR c++/38640
 	* semantics.c (finish_decltype_type): Handle TEMPLATE_PARM_INDEX.
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e21aa8e2ed9..545d3ddb387 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3308,16 +3308,39 @@ cp_parser_primary_expression (cp_parser *parser,
 	case RID_FUNCTION_NAME:
 	case RID_PRETTY_FUNCTION_NAME:
 	case RID_C99_FUNCTION_NAME:
-	  /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
-	     __func__ are the names of variables -- but they are
-	     treated specially.  Therefore, they are handled here,
-	     rather than relying on the generic id-expression logic
-	     below.  Grammatically, these names are id-expressions.
+	  {
+	    const char *name;
 
-	     Consume the token.  */
-	  token = cp_lexer_consume_token (parser->lexer);
-	  /* Look up the name.  */
-	  return finish_fname (token->u.value);
+	    /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
+	       __func__ are the names of variables -- but they are
+	       treated specially.  Therefore, they are handled here,
+	       rather than relying on the generic id-expression logic
+	       below.  Grammatically, these names are id-expressions.
+
+	       Consume the token.  */
+	    token = cp_lexer_consume_token (parser->lexer);
+
+	    switch (token->keyword)
+	      {
+	      case RID_FUNCTION_NAME:
+		name = "%<__FUNCTION__%>";
+		break;
+	      case RID_PRETTY_FUNCTION_NAME:
+		name = "%<__PRETTY_FUNCTION__%>";
+		break;
+	      case RID_C99_FUNCTION_NAME:
+		name = "%<__func__%>";
+		break;
+	      default:
+		gcc_unreachable ();
+	      }
+
+	    if (cp_parser_non_integral_constant_expression (parser, name))
+	      return error_mark_node;
+
+	    /* Look up the name.  */
+	    return finish_fname (token->u.value);
+	  }
 
 	case RID_VA_ARG:
 	  {
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6b66b92e547..9a8aaa14e2c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
 2008-12-31  Jakub Jelinek  <jakub@redhat.com>
 
+	PR c++/38647
+	* g++.dg/template/function1.C: New test.
+
 	PR c++/38640
 	* g++.dg/cpp0x/decltype15.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/template/function1.C b/gcc/testsuite/g++.dg/template/function1.C
new file mode 100644
index 00000000000..1097c5bf9c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/function1.C
@@ -0,0 +1,27 @@
+// PR c++/38647
+// { dg-do compile }
+
+template<const char *, int> struct A {};
+const char func[] = "abc";
+template<int N> struct A<func, N> {};	// { dg-error "cannot appear|is invalid" }
+
+char a1[1];
+A<a1, 0> a;
+
+template<const char *, int> struct B {};
+template<int N> struct B<__FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid" }
+
+char b1[1];
+B<b1, 0> b;
+
+template<const char *, int> struct C {};
+template<int N> struct C<__PRETTY_FUNCTION__, N> {};	// { dg-error "cannot appear|is invalid" }
+
+char c1[1];
+C<c1, 0> c;
+
+template<const char *, int> struct D {};
+template<int N> struct D<__func__, N> {};	// { dg-error "cannot appear|is invalid" }
+
+char d1[1];
+D<d1, 0> d;