diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 5a87fa485c6..d9636bad683 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8277,15 +8277,24 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 	      }
 	    else
 	      {
-		/* This detects for example:
-		     reinterpret_cast<void*>(sizeof 0)
-		*/
-		if (!ctx->quiet)
-		  error_at (loc, "%<reinterpret_cast<%T>(%E)%> is not "
-			    "a constant expression",
-			    type, op);
-		*non_constant_p = true;
-		return t;
+		if (TYPE_PTR_P (type)
+		    && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+		  /* INTEGER_CST with pointer-to-method type is only used
+		     for a virtual method in a pointer to member function.
+		     Don't reject those.  */
+		  ;
+		else
+		  {
+		    /* This detects for example:
+			 reinterpret_cast<void*>(sizeof 0)
+		    */
+		    if (!ctx->quiet)
+		      error_at (loc, "%<reinterpret_cast<%T>(%E)%> is not "
+				"a constant expression",
+				type, op);
+		    *non_constant_p = true;
+		    return t;
+		  }
 	      }
 	  }
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual22.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual22.C
new file mode 100644
index 00000000000..89330bf8620
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual22.C
@@ -0,0 +1,22 @@
+// PR c++/117615
+// { dg-do "compile" { target c++20 } }
+
+struct Base {
+    virtual void doit (int v) const {}
+};
+
+struct Derived : Base {
+    void doit (int v) const {}
+};
+
+using fn_t = void (Base::*)(int) const;
+
+struct Helper {
+    fn_t mFn;
+    constexpr Helper (auto && fn) : mFn(static_cast<fn_t>(fn)) {}
+};
+
+void foo () {
+    constexpr Helper h (&Derived::doit);
+    constexpr Helper h2 (&Base::doit);
+}
