[gcc r17-3240] c++: do not hash TYPENAME_TYPEs on pointers [PR124811]

Patrick Palka via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:cc08be7bf549072bf3699a57d3d37222e8c1087d

commit r17-3240-gcc08be7bf549072bf3699a57d3d37222e8c1087d
Author: Patrick Palka <[email protected]>
Date:   Wed Aug 12 15:58:39 2026 -0400

    c++: do not hash TYPENAME_TYPEs on pointers [PR124811]
    
    typename_htab is written to a precompiled header.  A hash table is
    streamed out slot array and all: gt_pch_nx() relocates the pointers
    inside the entries but leaves every entry in the slot it happened to
    occupy.  typename_hasher hashed on the addresses of the scope and the
    fullname, so the slots were chosen from addresses that ASLR randomises
    in the process writing the header, and they no longer correspond to the
    hash of anything once the header has been read back at a different
    address.
    
    Lookups then find a restored TYPENAME_TYPE only when it happens to lie
    on the probe sequence of the slot the new hash points at, so most miss
    and build a duplicate, and which ones miss depends on the layout the
    writing process had.  That makes a compile using a PCH differ from the
    same compile without one, and differ from itself between runs: the
    duplicates consume DECL_UIDs, every later DECL_UID shifts, and
    var-tracking hashes on DECL_UID, so .debug_loclists comes out different.
    
    Hash on TYPE_UID instead, which the header preserves, and use
    iterative_hash_template_arg to properly hash fullname which can be an
    arbitrary TEMPLATE_ID_EXPR.  (It's important to hash the fullname instead
    of just the name for sake of the PR c++/65328 compile-time-hog testcase.)
    
            PR c++/124811
    
    gcc/cp/ChangeLog:
    
            * decl.cc (typename_hasher::hash): Instead of pointer hashing,
            hash TYPE_HASH of context and use iterative_hash_template_arg
            to hash fullname.
    
    Co-authored-by: Bernhard M. Wiedemann <[email protected]>
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/decl.cc | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index b5d9ed058748..cb3eb74c3a1c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4926,8 +4926,12 @@ struct typename_hasher : ggc_ptr_hash<tree_node>
   hash (tree context, tree fullname)
   {
     hashval_t hash = 0;
-    hash = iterative_hash_object (context, hash);
-    hash = iterative_hash_object (fullname, hash);
+    hash = iterative_hash_hashval_t (TYPE_HASH (context), hash);
+    /* FULLNAME could be a template-id, so use iterative_hash_template_arg here.
+       And might as well set comparing_specializations for stronger hashing.  */
+    ++comparing_specializations;
+    hash = iterative_hash_template_arg (fullname, hash);
+    --comparing_specializations;
     return hash;
   }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.