https://gcc.gnu.org/g:5f7d74b555e8febd8b3def1f8e51742200f289ed

commit r16-6958-g5f7d74b555e8febd8b3def1f8e51742200f289ed
Author: Marek Polacek <[email protected]>
Date:   Fri Jan 16 14:13:16 2026 -0500

    c++: tighten up is_std_substitution
    
    During Reflection review it came up that is_std_substitution
    handles NAMESPACE_DECLs accidentally: it wants either a class or a
    class template, but is looking at the type of any decl.  With this
    patch, we return false for any _DECL except TYPE_DECL and
    DECL_CLASS_TEMPLATE_P, but let's verify that we now don't return false
    for something that used to yield true.
    
    gcc/cp/ChangeLog:
    
            * mangle.cc (is_std_substitution): Return false for any _DECL except
            TYPE_DECL and DECL_CLASS_TEMPLATE_P.  Verify that we don't return 
false
            for something that used to yield true.  Use NULL_TREE instead of 
NULL.
    
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/mangle.cc | 52 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 32 insertions(+), 20 deletions(-)

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 06bd396c03ef..4e1de2128242 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -478,7 +478,7 @@ add_substitution (tree node)
 }
 
 /* Helper function for find_substitution.  Returns nonzero if NODE,
-   which may be a decl or a CLASS_TYPE, is a template-id with template
+   which may be a class or a class template, is a template-id with template
    name of substitution_index[INDEX] in the ::std namespace, with
    global module attachment.  */
 
@@ -486,10 +486,28 @@ static bool
 is_std_substitution (const tree node,
                     const substitution_identifier_index_t index)
 {
-  tree type = NULL;
-  tree decl = NULL;
+  tree type = NULL_TREE;
+  tree decl = NULL_TREE;
 
-  if (DECL_P (node))
+  auto std_substitution_p = [&] (tree decl, tree type)
+    {
+      if (!DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl)))
+       return false;
+
+      if (!(TYPE_LANG_SPECIFIC (type) && TYPE_TEMPLATE_INFO (type)))
+       return false;
+
+      tree tmpl = TYPE_TI_TEMPLATE (type);
+      if (DECL_NAME (tmpl) != subst_identifiers[index])
+       return false;
+
+      if (modules_p () && get_originating_module (tmpl, true) >= 0)
+       return false;
+
+      return true;
+    };
+
+  if (TREE_CODE (node) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (node))
     {
       type = TREE_TYPE (node);
       decl = node;
@@ -500,23 +518,17 @@ is_std_substitution (const tree node,
       decl = TYPE_NAME (node);
     }
   else
-    /* These are not the droids you're looking for.  */
-    return false;
-
-  if (!DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl)))
-    return false;
-
-  if (!(TYPE_LANG_SPECIFIC (type) && TYPE_TEMPLATE_INFO (type)))
-    return false;
-
-  tree tmpl = TYPE_TI_TEMPLATE (type);
-  if (DECL_NAME (tmpl) != subst_identifiers[index])
-    return false;
-
-  if (modules_p () && get_originating_module (tmpl, true) >= 0)
-    return false;
+    {
+      /* We used to accept all _DECL nodes in this function but now we
+        only accept classes or class templates.  Verify that we don't
+        return false for something that used to yield true.  */
+      gcc_checking_assert (!DECL_P (node)
+                          || !std_substitution_p (node, TREE_TYPE (node)));
+      /* These are not the droids you're looking for.  */
+      return false;
+    }
 
-  return true;
+  return std_substitution_p (decl, type);
 }
 
 /* Return the ABI tags (the TREE_VALUE of the "abi_tag" attribute entry) for T,

Reply via email to