https://gcc.gnu.org/g:fd2afe61c2860a2b3e8f02a31bad86b768d16265

commit r16-6981-gfd2afe61c2860a2b3e8f02a31bad86b768d16265
Author: Marek Polacek <[email protected]>
Date:   Wed Jan 21 14:04:34 2026 -0500

    c++: fix user_provided_p
    
    A user-provided function is a user-declared function that is
    not explicitly defaulted or deleted on its first declaration
    ([dcl.fct.def.default]).  So,
    
      void bar (int, long) = delete;
    
    in namespace scope should not be user-provided.  But user_provided_p
    was mistakenly returning true for this case, so eval_is_user_provided
    had to work around that.
    
    This patch corrects user_provided_p.  It makes use of the fact that
    a function deleted after its first declaration is ill-formed
    rather than user-provided:
    
      void f();
      void f() = delete; // error, not first declaration
    
    gcc/cp/ChangeLog:
    
            * class.cc (user_provided_p): Return false for a deleted
            namespace-scope function.
            * reflect.cc (eval_is_user_provided): Don't check
            DECL_NAMESPACE_SCOPE_P or DECL_DELETED_FN.
    
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/class.cc   | 9 +++++++--
 gcc/cp/reflect.cc | 6 +-----
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index c610236f2601..6f00ca671e47 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -5726,7 +5726,7 @@ in_class_defaulted_default_constructor (tree t)
 }
 
 /* Returns true iff FN is a user-provided function, i.e. user-declared
-   and not defaulted at its first declaration.  */
+   and not explicitly defaulted or deleted on its first declaration.  */
 
 bool
 user_provided_p (tree fn)
@@ -5734,7 +5734,12 @@ user_provided_p (tree fn)
   fn = STRIP_TEMPLATE (fn);
   return (!DECL_ARTIFICIAL (fn)
          && !(DECL_INITIALIZED_IN_CLASS_P (fn)
-              && (DECL_DEFAULTED_FN (fn) || DECL_DELETED_FN (fn))));
+              && (DECL_DEFAULTED_FN (fn) || DECL_DELETED_FN (fn)))
+         /* At namespace scope,
+             void f () = delete;
+           is *not* user-provided (and any function deleted after its first
+           declaration is ill-formed).  */
+         && !(DECL_NAMESPACE_SCOPE_P (fn) && DECL_DELETED_FN (fn)));
 }
 
 /* Returns true iff class T has a user-provided constructor.  */
diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 0b0fc2769d88..788c00c6f305 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -1780,11 +1780,7 @@ static tree
 eval_is_user_provided (tree r)
 {
   r = maybe_get_first_fn (r);
-  if (TREE_CODE (r) == FUNCTION_DECL
-      && user_provided_p (r)
-      // TODO: user_provided_p is false for non-members defaulted on
-      // first declaration.
-      && (!DECL_NAMESPACE_SCOPE_P (r) || !DECL_DELETED_FN (r)))
+  if (TREE_CODE (r) == FUNCTION_DECL && user_provided_p (r))
     return boolean_true_node;
   else
     return boolean_false_node;

Reply via email to