diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1f8b270136605f740e960875207d87d781572335..3c6f25a1c149eb122bcf5c647c846cb7f83fa11a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2005-06-05  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/21619
+	* cp-tree.h (DECL_IS_BUILTIN_CONSTANT_P): New macro.
+	* parser.c (cp_parser_postfix_expression): Allow non-constant
+	expressions as arguments to __builtin_constant_p.
+	* tree.c (builtin_valid_in_constant_expr_p): Use
+	DECL_IS_BUILTIN_CONSTANT_P. 
+
 2005-06-03  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/21853
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0f3dfa5c89049e4765fe6ffb12c980bb7a2a0eaa..bcc6b3fc3ede1288bf6408b69ec73e2b71b5bfd8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1787,6 +1787,12 @@ struct lang_decl GTY(())
 #define DECL_HAS_IN_CHARGE_PARM_P(NODE) \
   (DECL_LANG_SPECIFIC (NODE)->decl_flags.has_in_charge_parm_p)
 
+/* Nonzero if DECL is a declaration of __builtin_constant_p.  */
+#define DECL_IS_BUILTIN_CONSTANT_P(NODE)		\
+ (TREE_CODE (NODE) == FUNCTION_DECL			\
+  && DECL_BUILT_IN_CLASS (NODE) == BUILT_IN_NORMAL	\
+  && DECL_FUNCTION_CODE (NODE) == BUILT_IN_CONSTANT_P)
+
 /* Nonzero for _DECL means that this decl appears in (or will appear
    in) as a member in a RECORD_TYPE or UNION_TYPE node.  It is also for
    detecting circularity in case members are multiply defined.  In the
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 27c1751cb02afce13f0a80a43202dd2809643c51..65442c769d0e3bb875618a42fa1c9f639138a2cc 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4121,10 +4121,34 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
 	  /* postfix-expression ( expression-list [opt] ) */
 	  {
 	    bool koenig_p;
-	    tree args = (cp_parser_parenthesized_expression_list
-			 (parser, false, 
-			  /*cast_p=*/false,
-			  /*non_constant_p=*/NULL));
+	    bool is_builtin_constant_p;
+	    bool saved_integral_constant_expression_p = false;
+	    bool saved_non_integral_constant_expression_p = false;
+	    tree args;
+
+	    is_builtin_constant_p 
+	      = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
+	    if (is_builtin_constant_p)
+	      {
+		/* The whole point of __builtin_constant_p is to allow
+		   non-constant expressions to appear as arguments.  */
+		saved_integral_constant_expression_p
+		  = parser->integral_constant_expression_p;
+		saved_non_integral_constant_expression_p
+		  = parser->non_integral_constant_expression_p;
+		parser->integral_constant_expression_p = false;
+	      }
+	    args = (cp_parser_parenthesized_expression_list
+		    (parser, /*is_attribute_list=*/false, 
+		     /*cast_p=*/false,
+		     /*non_constant_p=*/NULL));
+	    if (is_builtin_constant_p)
+	      {
+		parser->integral_constant_expression_p
+		  = saved_integral_constant_expression_p;
+		parser->non_integral_constant_expression_p
+		  = saved_non_integral_constant_expression_p;
+	      }
 
 	    if (args == error_mark_node)
 	      {
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8ef383c30eeaf8f890120568f383b18837787293..321988a1a2053508f418927a50fc225ae5a433c1 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -225,9 +225,7 @@ builtin_valid_in_constant_expr_p (tree decl)
 {
   /* At present BUILT_IN_CONSTANT_P is the only builtin we're allowing
      in constant-expressions.  We may want to add other builtins later. */
-  return TREE_CODE (decl) == FUNCTION_DECL
-    && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
-    && DECL_FUNCTION_CODE (decl) == BUILT_IN_CONSTANT_P;
+  return DECL_IS_BUILTIN_CONSTANT_P (decl);
 }
 
 /* Build a TARGET_EXPR, initializing the DECL with the VALUE.  */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 737245c99c52c24d0495ac2a8aae35bd78e58d91..0fa5e70056f25f8d98d3e2ba23da04290ff3aa6a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-06-05  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/21619
+	* g++.dg/ext/builtin9.C: New test.
+
 2005-06-05  Dale Johannesen  <dalej@apple.com>
 
 	* gcc.c-torture/execute/20050603-1.c:  Move to gcc.dg.
diff --git a/gcc/testsuite/g++.dg/ext/builtin9.C b/gcc/testsuite/g++.dg/ext/builtin9.C
new file mode 100644
index 0000000000000000000000000000000000000000..6b2b712deab46cfbf7e69deec83636a7e89e0c94
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin9.C
@@ -0,0 +1,3 @@
+// PR c++/21619
+// { dg-options "" }
+int f[__builtin_constant_p(&"Hello"[0])?1:-1];