--- a/configure	
+++ a/configure	
@@ -779,6 +779,7 @@ CFG_PULSEAUDIO=auto
 CFG_COREWLAN=auto
 CFG_ICD=auto
 CFG_NOPROCESS=no
+CFG_ICU=no
 
 # initalize variables used for installation
 QT_INSTALL_PREFIX=
@@ -940,7 +941,7 @@ while [ "$#" -gt 0 ]; do
         VAL=no
         ;;
     #Qt style yes options
-    -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles)
+    -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles|-icu)
         VAR=`echo $1 | sed "s,^-\(.*\),\1,"`
         VAL=yes
         ;;
@@ -2242,6 +2243,13 @@ while [ "$#" -gt 0 ]; do
           QT_CFLAGS_FPU=$VAL
        fi
        ;;
+    icu)
+        if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
+            CFG_ICU="$VAL"
+        else
+            UNKNOWN_OPT=yes
+        fi
+        ;;
     *)
         UNKNOWN_OPT=yes
         ;;
@@ -7040,6 +7048,10 @@ if [ "$CFG_ICD" = "yes" ]; then
     QT_CONFIG="$QT_CONFIG icd"
 fi
 
+if [ "$CFG_ICU" = "yes" ]; then
+    QT_CONFIG="$QT_CONFIG icu"
+fi
+
 #
 # Some Qt modules are too advanced in C++ for some old compilers
 # Detect here the platforms where they are known to work.
--- a/src/corelib/tools/qchar.cpp	
+++ a/src/corelib/tools/qchar.cpp	
@@ -57,6 +57,12 @@ 
 
 QT_BEGIN_NAMESPACE
 
+#ifdef QT_USE_ICU
+// from qlocale_icu.cpp
+extern uint qt_u_toUpper(uint c);
+extern uint qt_u_toLower(uint c);
+#endif
+
 #ifndef QT_NO_CODEC_FOR_C_STRINGS
 #  ifdef QT_NO_TEXTCODEC
 #    define QT_NO_CODEC_FOR_C_STRINGS
@@ -1076,6 +1082,12 @@ QChar::UnicodeVersion QChar::unicodeVersion(ushort ucs2)
 */
 QChar QChar::toLower() const
 {
+#ifdef QT_USE_ICU
+    uint res = qt_u_toLower(ucs);
+    if (res)
+        return QChar(res);
+    // else fall through
+#endif
     const QUnicodeTables::Properties *p = qGetProp(ucs);
     if (!p->lowerCaseSpecial)
         return ucs + p->lowerCaseDiff;
@@ -1090,6 +1102,12 @@ QChar QChar::toLower() const
 */
 uint QChar::toLower(uint ucs4)
 {
+#ifdef QT_USE_ICU
+    uint res = qt_u_toLower(ucs4);
+    if (res)
+        return res;
+    // else fall through
+#endif
     if (ucs4 > UNICODE_LAST_CODEPOINT)
         return ucs4;
     const QUnicodeTables::Properties *p = qGetProp(ucs4);
@@ -1106,6 +1124,12 @@ uint QChar::toLower(uint ucs4)
 */
 ushort QChar::toLower(ushort ucs2)
 {
+#ifdef QT_USE_ICU
+    uint res = qt_u_toLower(ucs2);
+    if (res)
+        return res & 0xffff;
+    // else fall through
+#endif
     const QUnicodeTables::Properties *p = qGetProp(ucs2);
     if (!p->lowerCaseSpecial)
         return ucs2 + p->lowerCaseDiff;
@@ -1118,6 +1142,12 @@ ushort QChar::toLower(ushort ucs2)
 */
 QChar QChar::toUpper() const
 {
+#ifdef QT_USE_ICU
+    uint res = qt_u_toUpper(ucs);
+    if (res)
+        return QChar(res);
+    // else fall through
+#endif
     const QUnicodeTables::Properties *p = qGetProp(ucs);
     if (!p->upperCaseSpecial)
         return ucs + p->upperCaseDiff;
@@ -1132,6 +1162,12 @@ QChar QChar::toUpper() const
 */
 uint QChar::toUpper(uint ucs4)
 {
+#ifdef QT_USE_ICU
+    uint res = qt_u_toUpper(ucs4);
+    if (res)
+        return res;
+    // else fall through
+#endif
     if (ucs4 > UNICODE_LAST_CODEPOINT)
         return ucs4;
     const QUnicodeTables::Properties *p = qGetProp(ucs4);
@@ -1148,6 +1184,12 @@ uint QChar::toUpper(uint ucs4)
 */
 ushort QChar::toUpper(ushort ucs2)
 {
+#ifdef QT_USE_ICU
+    uint res = qt_u_toUpper(ucs2);
+    if (res)
+        return res & 0xffff;
+    // else fall through
+#endif
     const QUnicodeTables::Properties *p = qGetProp(ucs2);
     if (!p->upperCaseSpecial)
         return ucs2 + p->upperCaseDiff;
--- a/src/corelib/tools/qlocale.cpp	
+++ a/src/corelib/tools/qlocale.cpp	
@@ -134,6 +134,10 @@ void qt_symbianUpdateSystemPrivate();
 void qt_symbianInitSystemLocale();
 #endif
 
+#ifdef QT_USE_ICU
+extern bool qt_initIcu(const QString &localeName);
+#endif
+
 /******************************************************************************
 ** Helpers for accessing Qt locale database
 */
@@ -2346,6 +2350,10 @@ void QLocale::setDefault(const QLocale &locale)
 {
     default_lp = locale.d();
     default_number_options = locale.numberOptions();
+
+#ifdef QT_USE_ICU
+    qt_initIcu(locale.name());
+#endif
 }
 
 /*!
--- a/src/corelib/tools/qlocale_icu.cpp	
+++ a/src/corelib/tools/qlocale_icu.cpp	
@@ -0,0 +1,247 @@ 
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+#include "qlibrary.h"
+#include "qdebug.h"
+
+#include "unicode/uversion.h"
+#include "unicode/ucol.h"
+
+QT_BEGIN_NAMESPACE
+
+typedef UCollator *(*Ptr_ucol_open)(const char *loc, UErrorCode *status);
+typedef void (*Ptr_ucol_close)(UCollator *coll);
+typedef UCollationResult (*Ptr_ucol_strcoll)(const UCollator *coll, const UChar *source, int32_t sourceLength, const UChar *target, int32_t targetLength);
+typedef int32_t (*Ptr_u_strToCase)(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode);
+
+static Ptr_ucol_open ptr_ucol_open = 0;
+static Ptr_ucol_strcoll ptr_ucol_strcoll = 0;
+static Ptr_ucol_close ptr_ucol_close = 0;
+static Ptr_u_strToCase ptr_u_strToUpper = 0;
+static Ptr_u_strToCase ptr_u_strToLower = 0;
+
+enum LibLoadStatus
+{
+    ErrorLoading = -1,
+    NotLoaded = 0,
+    Loaded = 1
+};
+
+static LibLoadStatus status = NotLoaded;
+
+static UCollator *icuCollator = 0;
+
+#define STRINGIFY2(x) #x
+#define STRINGIFY(x) STRINGIFY2(x)
+
+bool qt_initIcu(const QString &localeString)
+{
+    if (status == ErrorLoading)
+        return false;
+
+    if (status == NotLoaded) {
+
+        // resolve libicui18n
+        QLibrary lib(QLatin1String("icui18n"), QLatin1String(U_ICU_VERSION_SHORT));
+        if (!lib.load()) {
+            qWarning() << "Unable to load library icui18n" << lib.errorString();
+            status = ErrorLoading;
+            return false;
+        }
+
+        ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open");
+        ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close");
+        ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll");
+
+        if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) {
+            // try again with decorated symbol names
+            ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open" STRINGIFY(U_ICU_VERSION_SUFFIX));
+            ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close" STRINGIFY(U_ICU_VERSION_SUFFIX));
+            ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll" STRINGIFY(U_ICU_VERSION_SUFFIX));
+        }
+
+        if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) {
+            ptr_ucol_open = 0;
+            ptr_ucol_close = 0;
+            ptr_ucol_strcoll = 0;
+
+            qWarning("Unable to find symbols in icui18n");
+            status = ErrorLoading;
+            return false;
+        }
+
+        // resolve libicuuc
+        QLibrary ucLib(QLatin1String("icuuc"), QLatin1String(U_ICU_VERSION_SHORT));
+        if (!ucLib.load()) {
+            qWarning() << "Unable to load library icuuc" << ucLib.errorString();
+            status = ErrorLoading;
+            return false;
+        }
+
+        ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper");
+        ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower");
+
+        if (!ptr_u_strToUpper || !ptr_u_strToLower) {
+            ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper" STRINGIFY(U_ICU_VERSION_SUFFIX));
+            ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower" STRINGIFY(U_ICU_VERSION_SUFFIX));
+        }
+
+        if (!ptr_u_strToUpper || !ptr_u_strToLower) {
+            ptr_u_strToUpper = 0;
+            ptr_u_strToLower = 0;
+
+            qWarning("Unable to find symbols in icuuc");
+            status = ErrorLoading;
+            return false;
+        }
+
+        // success :)
+        status = Loaded;
+    }
+
+    if (icuCollator) {
+        ptr_ucol_close(icuCollator);
+        icuCollator = 0;
+    }
+
+    UErrorCode icuStatus = U_ZERO_ERROR;
+    icuCollator = ptr_ucol_open(localeString.toLatin1().constData(), &icuStatus);
+
+    if (!icuCollator) {
+        qWarning("Unable to open locale %s in ICU, error code %d", qPrintable(localeString), icuStatus);
+        return false;
+    }
+
+    return true;
+}
+
+bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result)
+{
+    Q_ASSERT(result);
+    Q_ASSERT(source);
+    Q_ASSERT(target);
+
+    if (!icuCollator)
+        return false;
+
+    *result = ptr_ucol_strcoll(icuCollator, reinterpret_cast<const UChar *>(source), int32_t(sourceLength),
+                               reinterpret_cast<const UChar *>(target), int32_t(targetLength));
+
+    return true;
+}
+
+// caseFunc can either be u_strToUpper or u_strToLower
+static bool qt_u_strToCase(const QString &str, QString *out, const QLocale &locale, Ptr_u_strToCase caseFunc)
+{
+    Q_ASSERT(out);
+
+    if (!icuCollator)
+        return false;
+
+    QString result(str.size(), Qt::Uninitialized);
+
+    UErrorCode status = U_ZERO_ERROR;
+
+    int32_t size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(),
+            reinterpret_cast<const UChar *>(str.constData()), str.size(),
+            locale.name().toLatin1().constData(), &status);
+
+    if (U_FAILURE(status))
+        return false;
+
+    if (size < result.size()) {
+        result.resize(size);
+    } else if (size > result.size()) {
+        qDebug() << "RESULT SIZE MISMATCH";
+        // the resulting string is larger than our source string
+        result.resize(size);
+
+        status = U_ZERO_ERROR;
+        size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(),
+            reinterpret_cast<const UChar *>(str.constData()), str.size(),
+            locale.name().toLatin1().constData(), &status);
+
+        if (U_FAILURE(status))
+            return false;
+
+        // if the sizes don't match now, we give up.
+        if (size != result.size())
+            return false;
+    }
+
+    *out = result;
+    return true;
+}
+
+bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale)
+{
+    return qt_u_strToCase(str, out, locale, ptr_u_strToUpper);
+}
+
+bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale)
+{
+    return qt_u_strToCase(str, out, locale, ptr_u_strToLower);
+}
+
+uint qt_u_toUpper(uint c)
+{
+    if (c > 0xffff)
+        return 0;
+
+    QString out;
+    if (qt_u_strToUpper(QChar(c), &out, QLocale()) && !out.isEmpty())
+        return out.at(0).unicode();
+    return 0;
+}
+
+uint qt_u_toLower(uint c)
+{
+    if (c > 0xffff)
+        return 0;
+
+    QString out;
+    if (qt_u_strToLower(QChar(c), &out, QLocale()) && !out.isEmpty())
+        return out.at(0).unicode();
+    return 0;
+}
+
+QT_END_NAMESPACE
--- a/src/corelib/tools/qstring.cpp	
+++ a/src/corelib/tools/qstring.cpp	
@@ -112,6 +112,13 @@ int qFindString(const QChar *haystack, int haystackLen, int from,
 int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from,
     const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
 
+#ifdef QT_USE_ICU
+// qlocale_icu.cpp
+extern bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result);
+extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale);
+extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale);
+#endif
+
 
 // Unicode case-insensitive comparison
 static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be)
@@ -4808,6 +4815,14 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
     TPtrC p2 = TPtrC16(reinterpret_cast<const TUint16 *>(data2), length2);
     return p1.CompareC(p2);
 #elif defined(Q_OS_UNIX)
+#  if defined(QT_USE_ICU)
+    int res;
+    if (qt_ucol_strcoll(data1, length1, data2, length2, &res)) {
+        if (res == 0)
+            res = ucstrcmp(data1, length1, data2, length2);
+        return res;
+    } // else fall through
+#  endif
     // declared in <string.h>
     int delta = strcoll(toLocal8Bit_helper(data1, length1), toLocal8Bit_helper(data2, length2));
     if (delta == 0)
@@ -4943,6 +4958,15 @@ QString QString::toLower() const
     if (!d->size)
         return *this;
 
+#ifdef QT_USE_ICU
+    {
+        QString result;
+        if (qt_u_strToLower(*this, &result, QLocale()))
+            return result;
+        // else fall through and use Qt's toUpper
+    }
+#endif
+
     const ushort *e = d->data + d->size;
 
     // this avoids one out of bounds check in the loop
@@ -5034,6 +5058,15 @@ QString QString::toUpper() const
     if (!d->size)
         return *this;
 
+#ifdef QT_USE_ICU
+    {
+        QString result;
+        if (qt_u_strToUpper(*this, &result, QLocale()))
+            return result;
+        // else fall through and use Qt's toUpper
+    }
+#endif
+
     const ushort *e = d->data + d->size;
 
     // this avoids one out of bounds check in the loop
--- a/src/corelib/tools/tools.pri	
+++ a/src/corelib/tools/tools.pri	
@@ -92,6 +92,11 @@ else:SOURCES += tools/qelapsedtimer_generic.cpp
 contains(QT_CONFIG, zlib):include($$PWD/../../3rdparty/zlib.pri)
 else:include($$PWD/../../3rdparty/zlib_dependency.pri)
 
+contains(QT_CONFIG,icu) {
+    SOURCES += tools/qlocale_icu.cpp
+    DEFINES += QT_USE_ICU
+}
+
 DEFINES += HB_EXPORT=Q_CORE_EXPORT
 INCLUDEPATH += ../3rdparty/harfbuzz/src
 HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h
--- a/tests/auto/qchar/qchar.pro	
+++ a/tests/auto/qchar/qchar.pro	
@@ -13,3 +13,5 @@ symbian: {
 } else {
     DEFINES += SRCDIR=\\\"$$PWD/\\\"
 }
+
+contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU
--- a/tests/auto/qchar/tst_qchar.cpp	
+++ a/tests/auto/qchar/tst_qchar.cpp	
@@ -103,7 +103,8 @@ tst_QChar::~tst_QChar()
 { }
 
 void tst_QChar::initTestCase()
-{ }
+{
+}
 
 void tst_QChar::cleanupTestCase()
 { }
@@ -114,6 +115,7 @@ void tst_QChar::init()
     int argc = 0;
     app = new QCoreApplication(argc, NULL);
 #endif
+    QLocale::setDefault(QLocale::C);
 }
 
 void tst_QChar::cleanup()
@@ -143,9 +145,36 @@ void tst_QChar::toUpper()
     QVERIFY(QChar::toUpper((uint)0x1c8) == 0x1c7);
     QVERIFY(QChar::toUpper((uint)0x1c9) == 0x1c7);
 
-    QVERIFY(QChar::toUpper((uint)0x10400) == 0x10400);
-    QVERIFY(QChar::toUpper((uint)0x10428) == 0x10400);
+    QCOMPARE(QChar::toUpper((uint)0x10400), 0x10400u);
+    QCOMPARE(QChar::toUpper((uint)0x10428), 0x10400u);
+
+#ifdef QT_USE_ICU
+    QCOMPARE(QChar('i').toUpper(), QChar('I'));
+    QCOMPARE(QChar::toUpper(ushort('i')), ushort('I'));
+    QCOMPARE(QChar::toUpper(uint('i')), uint('I'));
+
+    QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey));
+
+    // in Turkish locale, upper-caseing a 'i' will result in a capital I plus dot (0x0130)
+    QCOMPARE(QChar('i').toUpper(), QChar(0x0130u));
+    QCOMPARE(QChar::toUpper(ushort('i')), ushort(0x0130u));
+    QCOMPARE(QChar::toUpper(uint('i')), 0x0130u);
+
+    // upper-casing a lower-case i without dot (0x0131) will result in 'I'
+    QCOMPARE(QChar(0x0131u).toUpper(), QChar('I'));
+    QCOMPARE(QChar::toUpper(ushort(0x0131u)), ushort('I'));
+    QCOMPARE(QChar::toUpper(uint(0x0131u)), uint('I'));
+
+    // upper-casing an upper-case 0x0130 should do nothing
+    QCOMPARE(QChar(0x0130u).toUpper(), QChar(0x0130u));
+    QCOMPARE(QChar::toUpper(ushort(0x0130u)), ushort(0x0130u));
+    QCOMPARE(QChar::toUpper(uint(0x0130u)), uint(0x0130u));
 
+    // upper-casing an upper-case I should do nothing
+    QCOMPARE(QChar('I').toUpper(), QChar('I'));
+    QCOMPARE(QChar::toUpper(ushort('I')), ushort('I'));
+    QCOMPARE(QChar::toUpper(uint('I')), uint('I'));
+#endif
 }
 
 void tst_QChar::toLower()
@@ -170,6 +199,34 @@ void tst_QChar::toLower()
 
     QVERIFY(QChar::toLower((uint)0x10400) == 0x10428);
     QVERIFY(QChar::toLower((uint)0x10428) == 0x10428);
+
+#ifdef QT_USE_ICU
+    QCOMPARE(QChar('I').toLower(), QChar('i'));
+    QCOMPARE(QChar::toLower(ushort('I')), ushort('i'));
+    QCOMPARE(QChar::toLower(uint('I')), uint('i'));
+
+    QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey));
+
+    // in turkish locale, lower-casing an 'I' will result with a lower-case i without dot (0x0131)
+    QCOMPARE(QChar('I').toLower(), QChar(0x0131u));
+    QCOMPARE(QChar::toLower(ushort('I')), ushort(0x0131u));
+    QCOMPARE(QChar::toLower(uint('I')), uint(0x0131u));
+
+    // lower-casing a captial I with dot (0x0130) will result in 'i'
+    QCOMPARE(QChar(0x0130u).toLower(), QChar('i'));
+    QCOMPARE(QChar::toLower(ushort(0x0130u)), ushort('i'));
+    QCOMPARE(QChar::toLower(uint(0x0130u)), uint('i'));
+
+    // lower-casing a lower-case i should do nothing
+    QCOMPARE(QChar('i').toLower(), QChar('i'));
+    QCOMPARE(QChar::toLower(ushort('i')), ushort('i'));
+    QCOMPARE(QChar::toLower(uint('i')), uint('i'));
+
+    // lower-casing a lower-case i without dot (0x0131) should do nothing
+    QCOMPARE(QChar(0x0131u).toLower(), QChar(0x0131u));
+    QCOMPARE(QChar::toLower(ushort(0x0131u)), ushort(0x0131u));
+    QCOMPARE(QChar::toLower(uint(0x0131u)), uint(0x0131u));
+#endif
 }
 
 void tst_QChar::toTitle()
--- a/tests/auto/qstring/qstring.pro	
+++ a/tests/auto/qstring/qstring.pro	
@@ -6,3 +6,5 @@ symbian:LIBS += -llibm
 QT = core
 
 DEFINES += QT_NO_CAST_TO_ASCII
+
+contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU
--- a/tests/auto/qstring/tst_qstring.cpp	
+++ a/tests/auto/qstring/tst_qstring.cpp	
@@ -210,6 +210,8 @@ private slots:
     void task262677remove();
     void QTBUG10404_compareRef();
     void QTBUG9281_arg_locale();
+
+    void toUpperLower_icu();
 };
 
 typedef QList<int> IntList;
@@ -1544,6 +1546,11 @@ void tst_QString::toUpper()
     QCOMPARE( lower.toUpper(), upper);
 
 
+#ifdef QT_USE_ICU
+    // test doesn't work with ICU support, since QChar is unaware of any locale
+    QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue);
+    QVERIFY(false);
+#else
     for (int i = 0; i < 65536; ++i) {
         QString str(1, QChar(i));
         QString upper = str.toUpper();
@@ -1551,6 +1558,7 @@ void tst_QString::toUpper()
         if (upper.length() == 1)
             QVERIFY(upper == QString(1, QChar(i).toUpper()));
     }
+#endif
 }
 
 void tst_QString::toLower()
@@ -1582,6 +1590,11 @@ void tst_QString::toLower()
     upper += QChar(QChar::lowSurrogate(0x10400));
     QCOMPARE( upper.toLower(), lower);
 
+#ifdef QT_USE_ICU
+    // test doesn't work with ICU support, since QChar is unaware of any locale
+    QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue);
+    QVERIFY(false);
+#else
     for (int i = 0; i < 65536; ++i) {
         QString str(1, QChar(i));
         QString lower = str.toLower();
@@ -1589,6 +1602,7 @@ void tst_QString::toLower()
         if (lower.length() == 1)
             QVERIFY(str.toLower() == QString(1, QChar(i).toLower()));
     }
+#endif
 }
 
 void tst_QString::trimmed()
@@ -4200,6 +4214,8 @@ void tst_QString::localeAwareCompare()
 
 #elif defined (Q_WS_MAC)
     QSKIP("Setting the locale is not supported on OS X (you can set the C locale, but that won't affect CFStringCompare which is used to compare strings)", SkipAll);
+#elif defined(QT_USE_ICU)
+    QLocale::setDefault(QLocale(locale));
 #else
     if (!locale.isEmpty()) {
         const char *newLocale = setlocale(LC_ALL, locale.toLatin1());
@@ -4211,6 +4227,11 @@ void tst_QString::localeAwareCompare()
     }
 #endif
 
+#ifdef QT_USE_ICU
+    // ### for c1, ICU disagrees with libc on how to compare
+    QEXPECT_FAIL("c1", "ICU disagrees with test", Abort);
+#endif
+
     int testres = QString::localeAwareCompare(s1, s2);
     if (result < 0) {
         QVERIFY(testres < 0);
@@ -4912,6 +4933,40 @@ void tst_QString::QTBUG9281_arg_locale()
     QLocale::setDefault(QLocale::C);
 }
 
+void tst_QString::toUpperLower_icu()
+{
+#ifndef QT_USE_ICU
+    QSKIP("Qt was built without ICU support", QTest::SkipAll);
+#endif
+
+    QString s = QString::fromLatin1("i");
+
+    QCOMPARE(s.toUpper(), QString::fromLatin1("I"));
+    QCOMPARE(s.toLower(), QString::fromLatin1("i"));
+
+    QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey));
+
+    // turkish locale has a capital I with a dot (U+0130, utf8 c4b0)
+
+    QCOMPARE(s.toUpper(), QString::fromUtf8("\xc4\xb0"));
+    QCOMPARE(QString::fromUtf8("\xc4\xb0").toLower(), s);
+
+    // nothing should happen here
+    QCOMPARE(s.toLower(), s);
+    QCOMPARE(QString::fromLatin1("I").toUpper(), QString::fromLatin1("I"));
+
+    // U+0131, utf8 c4b1 is the lower-case i without a dot
+    QString sup = QString::fromUtf8("\xc4\xb1");
+
+    QCOMPARE(sup.toUpper(), QString::fromLatin1("I"));
+    QCOMPARE(QString::fromLatin1("I").toLower(), sup);
+
+    // nothing should happen here
+    QCOMPARE(sup.toLower(), sup);
+    QCOMPARE(QString::fromLatin1("i").toLower(), QString::fromLatin1("i"));
+
+    // the cleanup function will restore the default locale
+}
 
 
 QTEST_APPLESS_MAIN(tst_QString)
