diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index ed756cbeb609c7fc923b6e116ea2f0e833178b5c..59e7a979dcd5d7fe5bb16e96ccdba8f354257f18 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -235,17 +235,16 @@ static void qt_initialize_qhash_seed()
     \internal
 
     Private copy of the implementation of the Qt 4 qHash algorithm for strings,
+    (that is, QChar-based arrays, so all QString-like classes),
     to be used wherever the result is somehow stored or reused across multiple
     Qt versions. The public qHash implementation can change at any time,
     therefore one must not rely on the fact that it will always give the same
     results.
 
-    This function must *never* change its results.
+    The qt_hash functions must *never* change their results.
 */
-uint qt_hash(const QString &key) Q_DECL_NOTHROW
+static uint qt_hash(const QChar *p, int n) Q_DECL_NOTHROW
 {
-    const QChar *p = key.unicode();
-    int n = key.size();
     uint h = 0;
 
     while (n--) {
@@ -256,6 +255,24 @@ uint qt_hash(const QString &key) Q_DECL_NOTHROW
     return h;
 }
 
+/*!
+    \internal
+    \overload
+*/
+uint qt_hash(const QString &key) Q_DECL_NOTHROW
+{
+    return qt_hash(key.unicode(), key.size());
+}
+
+/*!
+    \internal
+    \overload
+*/
+uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW
+{
+    return qt_hash(key.unicode(), key.size());
+}
+
 /*
     The prime_deltas array is a table of selected prime values, even
     though it doesn't look like one. The primes we are using are 1,
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 5d9238f4538e9f2290ec72129d96d8799bfd9e83..e99a67d1e3a8a456f5002a8d21d8bab9dff62db6 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -92,6 +92,7 @@ Q_CORE_EXPORT uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
 Q_CORE_EXPORT uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
 Q_CORE_EXPORT uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
 Q_CORE_EXPORT uint qt_hash(const QString &key) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW;
 
 #if defined(Q_CC_MSVC)
 #pragma warning( push )
diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
index 1cbf18128601d53cd3bcbabd33dfa18803e3516e..71428310b832560a9be10e6d8e20a7353f8091e5 100644
--- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp
+++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
@@ -75,6 +75,9 @@ private slots:
     void const_shared_null();
     void twoArguments_qHash();
     void initializerList();
+
+    void qthash_data();
+    void qthash();
 };
 
 struct Foo {
@@ -1330,5 +1333,24 @@ void tst_QHash::initializerList()
 #endif
 }
 
+void tst_QHash::qthash_data()
+{
+    QTest::addColumn<QString>("key");
+    QTest::addColumn<uint>("hash");
+
+    QTest::newRow("null") << QString() << 0u;
+    QTest::newRow("empty") << QStringLiteral("") << 0u;
+    QTest::newRow("abcdef") << QStringLiteral("abcdef") << 108567222u;
+    QTest::newRow("tqbfjotld") << QStringLiteral("The quick brown fox jumps over the lazy dog") << 140865879u;
+    QTest::newRow("42") << QStringLiteral("42") << 882u;
+}
+
+void tst_QHash::qthash()
+{
+    QFETCH(QString, key);
+    const uint result = qt_hash(key);
+    QTEST(result, "hash");
+}
+
 QTEST_APPLESS_MAIN(tst_QHash)
 #include "tst_qhash.moc"