diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index dc29c8a75ea900e0b98b41bb5ea0c9c31996a7cc..08878d26720c8f2de48e10788154250fd16f3dd4 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -69,13 +69,16 @@ using namespace ProFileEvaluatorInternal;
 
 QT_BEGIN_NAMESPACE
 
-static void refFunctions(QHash<QString, ProFunctionDef *> *defs)
+using namespace ProStringConstants;
+
+
+static void refFunctions(QHash<ProString, ProFunctionDef *> *defs)
 {
     foreach (ProFunctionDef *itm, *defs)
         itm->ref();
 }
 
-static void clearFunctions(QHash<QString, ProFunctionDef *> *defs)
+static void clearFunctions(QHash<ProString, ProFunctionDef *> *defs)
 {
     foreach (ProFunctionDef *itm, *defs)
         itm->deref();
@@ -248,18 +251,18 @@ public:
     void visitProVariable(ProVariable *variable);
     ProItem::ProItemReturn visitProCondition(ProCondition *condition);
 
-    static inline QString map(const QString &var);
-    QHash<QString, QStringList> *findValues(const QString &variableName,
-                                            QHash<QString, QStringList>::Iterator *it);
-    QStringList &valuesRef(const QString &variableName);
-    QStringList valuesDirect(const QString &variableName) const;
-    QStringList values(const QString &variableName) const;
+    static inline ProString map(const ProString &var);
+    QHash<ProString, ProStringList> *findValues(const ProString &variableName,
+                                                QHash<ProString, ProStringList>::Iterator *it);
+    ProStringList &valuesRef(const ProString &variableName);
+    ProStringList valuesDirect(const ProString &variableName) const;
+    ProStringList values(const ProString &variableName) const;
     QString propertyValue(const QString &val, bool complain = true) const;
 
-    static QStringList split_value_list(const QString &vals);
+    static ProStringList split_value_list(const QString &vals);
     bool isActiveConfig(const QString &config, bool regex = false);
-    QStringList expandVariableReferences(const QString &value, int *pos = 0, bool joined = false);
-    QStringList evaluateExpandFunction(const QString &function, const QString &arguments);
+    ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false);
+    ProStringList evaluateExpandFunction(const ProString &function, const ProString &arguments);
     QString format(const char *format) const;
     void logMessage(const QString &msg) const;
     void errorMessage(const QString &msg) const;
@@ -271,20 +274,20 @@ public:
     QString resolvePath(const QString &fileName) const
         { return IoUtils::resolvePath(currentDirectory(), fileName); }
 
-    ProItem::ProItemReturn evaluateConditionalFunction(const QString &function, const QString &arguments);
+    ProItem::ProItemReturn evaluateConditionalFunction(const ProString &function, const ProString &arguments);
     ProFile *parsedProFile(const QString &fileName, bool cache,
                            const QString &contents = QString());
     bool evaluateFile(const QString &fileName);
     bool evaluateFeatureFile(const QString &fileName,
-                             QHash<QString, QStringList> *values = 0, FunctionDefs *defs = 0);
+                             QHash<ProString, ProStringList> *values = 0, FunctionDefs *defs = 0);
     bool evaluateFileInto(const QString &fileName,
-                          QHash<QString, QStringList> *values, FunctionDefs *defs);
+                          QHash<ProString, ProStringList> *values, FunctionDefs *defs);
 
     static inline ProItem::ProItemReturn returnBool(bool b)
         { return b ? ProItem::ReturnTrue : ProItem::ReturnFalse; }
 
-    QList<QStringList> prepareFunctionArgs(const QString &arguments);
-    QStringList evaluateFunction(ProFunctionDef *func, const QList<QStringList> &argumentsList, bool *ok);
+    QList<ProStringList> prepareFunctionArgs(const ProString &arguments);
+    ProStringList evaluateFunction(ProFunctionDef *func, const QList<ProStringList> &argumentsList, bool *ok);
 
     QStringList qmakeMkspecPaths() const;
     QStringList qmakeFeaturePaths() const;
@@ -298,9 +301,10 @@ public:
 
     int m_listCount;
     FunctionDefs m_functionDefs;
-    QStringList m_returnValue;
-    QStack<QHash<QString, QStringList> > m_valuemapStack;         // VariableName must be us-ascii, the content however can be non-us-ascii.
-    QHash<const ProFile*, QHash<QString, QStringList> > m_filevaluemap; // Variables per include file
+    ProStringList m_returnValue;
+    QStack<QHash<ProString, ProStringList> > m_valuemapStack;         // VariableName must be us-ascii, the content however can be non-us-ascii.
+    QHash<const ProFile*, QHash<ProString, ProStringList> > m_filevaluemap; // Variables per include file
+    QString m_tmp1, m_tmp2, m_tmp3, m_tmp[2]; // Temporaries for efficient toQString
 
     QStringList m_addUserConfigCmdArgs;
     QStringList m_removeUserConfigCmdArgs;
@@ -350,8 +354,8 @@ static struct {
     QString strmac9;
     QString strmac;
     QString strwin32;
-    QString strCONFIG;
-    QString strARGS;
+    ProString strCONFIG;
+    ProString strARGS;
     QString strDot;
     QString strDotDot;
     QString strfor;
@@ -359,14 +363,14 @@ static struct {
     QString strforever;
     QString strdefineTest;
     QString strdefineReplace;
-    QString strTEMPLATE;
-    QString strQMAKE_DIR_SEP;
+    ProString strTEMPLATE;
+    ProString strQMAKE_DIR_SEP;
     QHash<QString, int> expands;
-    QHash<QString, int> functions;
-    QHash<QString, int> varList;
-    QHash<QString, QString> varMap;
+    QHash<ProString, int> functions;
+    QHash<ProString, int> varList;
+    QHash<ProString, ProString> varMap;
     QRegExp reg_variableName;
-    QStringList fakeValue;
+    ProStringList fakeValue;
 } statics;
 
 void ProFileEvaluator::Private::initStatics()
@@ -384,8 +388,8 @@ void ProFileEvaluator::Private::initStatics()
     statics.strmac9 = QLatin1String("mac9");
     statics.strmac = QLatin1String("mac");
     statics.strwin32 = QLatin1String("win32");
-    statics.strCONFIG = QLatin1String("CONFIG");
-    statics.strARGS = QLatin1String("ARGS");
+    statics.strCONFIG = ProString("CONFIG");
+    statics.strARGS = ProString("ARGS");
     statics.strDot = QLatin1String(".");
     statics.strDotDot = QLatin1String("..");
     statics.strfor = QLatin1String("for");
@@ -393,8 +397,8 @@ void ProFileEvaluator::Private::initStatics()
     statics.strforever = QLatin1String("forever");
     statics.strdefineTest = QLatin1String("defineTest");
     statics.strdefineReplace = QLatin1String("defineReplace");
-    statics.strTEMPLATE = QLatin1String("TEMPLATE");
-    statics.strQMAKE_DIR_SEP = QLatin1String("QMAKE_DIR_SEP");
+    statics.strTEMPLATE = ProString("TEMPLATE");
+    statics.strQMAKE_DIR_SEP = ProString("QMAKE_DIR_SEP");
 
     statics.reg_variableName.setPattern(QLatin1String("\\$\\(.*\\)"));
     statics.reg_variableName.setMinimal(true);
@@ -468,7 +472,7 @@ void ProFileEvaluator::Private::initStatics()
         { "error", T_MESSAGE },
     };
     for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i)
-        statics.functions.insert(QLatin1String(testInits[i].name), testInits[i].func);
+        statics.functions.insert(ProString(testInits[i].name), testInits[i].func);
 
     static const char * const names[] = {
         "LITERAL_DOLLAR", "LITERAL_HASH", "LITERAL_WHITESPACE",
@@ -480,7 +484,7 @@ void ProFileEvaluator::Private::initStatics()
         "_DATE_", "_QMAKE_CACHE_"
     };
     for (unsigned i = 0; i < sizeof(names)/sizeof(names[0]); ++i)
-        statics.varList.insert(QLatin1String(names[i]), i);
+        statics.varList.insert(ProString(names[i]), i);
 
     static const struct {
         const char * const oldname, * const newname;
@@ -506,11 +510,11 @@ void ProFileEvaluator::Private::initStatics()
         { "QMAKE_FRAMEWORKDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS" }
     };
     for (unsigned i = 0; i < sizeof(mapInits)/sizeof(mapInits[0]); ++i)
-        statics.varMap.insert(QLatin1String(mapInits[i].oldname),
-                              QLatin1String(mapInits[i].newname));
+        statics.varMap.insert(ProString(mapInits[i].oldname),
+                              ProString(mapInits[i].newname));
 }
 
-QString ProFileEvaluator::Private::map(const QString &var)
+ProString ProFileEvaluator::Private::map(const ProString &var)
 {
     return statics.varMap.value(var, var);
 }
@@ -531,7 +535,7 @@ ProFileEvaluator::Private::Private(ProFileEvaluator *q_, ProFileOption *option)
     m_skipLevel = 0;
     m_loopLevel = 0;
     m_listCount = 0;
-    m_valuemapStack.push(QHash<QString, QStringList>());
+    m_valuemapStack.push(QHash<ProString, ProStringList>());
 }
 
 ProFileEvaluator::Private::~Private()
@@ -843,7 +847,7 @@ ProVariable *ProFileEvaluator::Private::startVariable(ushort *uc, ushort *ptr)
         --ptr;
 
   skipTrunc:
-    ProVariable *variable = new ProVariable(map(QString((QChar*)uc, ptr - uc)));
+    ProVariable *variable = new ProVariable(map(ProString(QString((QChar*)uc, ptr - uc))));
     variable->setLineNumber(m_lineNo);
     variable->setVariableOperator(opkind);
     return variable;
@@ -851,7 +855,7 @@ ProVariable *ProFileEvaluator::Private::startVariable(ushort *uc, ushort *ptr)
 
 void ProFileEvaluator::Private::finalizeVariable(ProVariable *variable, ushort *uc, ushort *ptr)
 {
-    variable->setValue(QString((QChar*)uc, ptr - uc));
+    variable->setValue(ProString(QString((QChar*)uc, ptr - uc), NoHash));
 
     m_blockstack.top().cursor.append(variable);
 }
@@ -1058,10 +1062,12 @@ void ProFileEvaluator::Private::updateItem(ushort *uc, ushort *ptr)
 
 //////// Evaluator tools /////////
 
-QStringList ProFileEvaluator::Private::split_value_list(const QString &vals)
+// FIXME: this should not build new strings for direct sections.
+// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy.
+ProStringList ProFileEvaluator::Private::split_value_list(const QString &vals)
 {
     QString build;
-    QStringList ret;
+    ProStringList ret;
     QStack<char> quote;
 
     const ushort SPACE = ' ';
@@ -1090,40 +1096,51 @@ QStringList ProFileEvaluator::Private::split_value_list(const QString &vals)
         }
 
         if (!parens && quote.isEmpty() && vals_data[x] == SPACE) {
-            ret << build;
+            ret << ProString(build, NoHash);
             build.clear();
         } else {
             build += vals_data[x];
         }
     }
     if (!build.isEmpty())
-        ret << build;
+        ret << ProString(build, NoHash);
     return ret;
 }
 
-static void insertUnique(QStringList *varlist, const QStringList &value)
+static void insertUnique(ProStringList *varlist, const ProStringList &value)
 {
-    foreach (const QString &str, value)
+    foreach (const ProString &str, value)
         if (!varlist->contains(str))
             varlist->append(str);
 }
 
-static void removeEach(QStringList *varlist, const QStringList &value)
+static void removeAll(ProStringList *varlist, const ProString &value)
 {
-    foreach (const QString &str, value)
-        varlist->removeAll(str);
+    for (int i = varlist->size(); --i >= 0; )
+        if (varlist->at(i) == value)
+            varlist->remove(i);
 }
 
-static void replaceInList(QStringList *varlist,
-        const QRegExp &regexp, const QString &replace, bool global)
+static void removeEach(ProStringList *varlist, const ProStringList &value)
 {
-    for (QStringList::Iterator varit = varlist->begin(); varit != varlist->end(); ) {
-        if ((*varit).contains(regexp)) {
-            (*varit).replace(regexp, replace);
-            if ((*varit).isEmpty())
+    foreach (const ProString &str, value)
+        removeAll(varlist, str);
+}
+
+static void replaceInList(ProStringList *varlist,
+        const QRegExp &regexp, const QString &replace, bool global, QString &tmp)
+{
+    for (ProStringList::Iterator varit = varlist->begin(); varit != varlist->end(); ) {
+        QString val = varit->toQString(tmp);
+        QString copy = val; // Force detach and have a reference value
+        val.replace(regexp, replace);
+        if (!val.isSharedWith(copy)) {
+            if (val.isEmpty()) {
                 varit = varlist->erase(varit);
-            else
+            } else {
+                *varit = ProString(val);
                 ++varit;
+            }
             if (!global)
                 break;
         } else {
@@ -1143,14 +1160,6 @@ static QString expandEnvVars(const QString &str)
     return string;
 }
 
-static QStringList expandEnvVars(const QStringList &x)
-{
-    QStringList ret;
-    foreach (const QString &str, x)
-        ret << expandEnvVars(str);
-    return ret;
-}
-
 // This is braindead, but we want qmake compat
 static QString fixPathToLocalOS(const QString &str)
 {
@@ -1167,8 +1176,9 @@ static QString fixPathToLocalOS(const QString &str)
     return string;
 }
 
-static bool isTrue(const QString &str)
+static bool isTrue(const ProString &_str, QString &tmp)
 {
+    const QString &str = _str.toQString(tmp);
     return !str.compare(statics.strtrue, Qt::CaseInsensitive) || str.toInt();
 }
 
@@ -1251,7 +1261,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProBlock(ProItem *items)
 
 void ProFileEvaluator::Private::visitProFunctionDef(ProFunctionDef *def)
 {
-    QHash<QString, ProFunctionDef *> *hash =
+    QHash<ProString, ProFunctionDef *> *hash =
             (def->type() == ProFunctionDef::TestFunction
              ? &m_functionDefs.testFunctions
              : &m_functionDefs.replaceFunctions);
@@ -1266,38 +1276,38 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProLoop(ProLoop *loop)
     ProItem::ProItemReturn ret = ProItem::ReturnTrue;
     bool infinite = false;
     int index = 0;
-    QString variable;
-    QStringList oldVarVal;
-    QString it_list = expandVariableReferences(loop->expression(), 0, true).first();
+    ProString variable;
+    ProStringList oldVarVal;
+    ProString it_list = expandVariableReferences(loop->expression(), 0, true).first();
     if (loop->variable().isEmpty()) {
         if (it_list != statics.strever) {
             logMessage(format("Invalid loop expression."));
             return ProItem::ReturnFalse;
         }
-        it_list = statics.strforever;
+        it_list = ProString(statics.strforever);
     } else {
         variable = map(loop->variable());
         oldVarVal = valuesDirect(variable);
-        it_list = map(it_list);
     }
-    QStringList list = valuesDirect(it_list);
+    ProStringList list = valuesDirect(it_list);
     if (list.isEmpty()) {
         if (it_list == statics.strforever) {
             infinite = true;
         } else {
-            int dotdot = it_list.indexOf(statics.strDotDot);
+            const QString &itl = it_list.toQString(m_tmp1);
+            int dotdot = itl.indexOf(statics.strDotDot);
             if (dotdot != -1) {
                 bool ok;
-                int start = it_list.left(dotdot).toInt(&ok);
+                int start = itl.left(dotdot).toInt(&ok);
                 if (ok) {
-                    int end = it_list.mid(dotdot+2).toInt(&ok);
+                    int end = itl.mid(dotdot+2).toInt(&ok);
                     if (ok) {
                         if (start < end) {
                             for (int i = start; i <= end; i++)
-                                list << QString::number(i);
+                                list << ProString(QString::number(i), NoHash);
                         } else {
                             for (int i = start; i >= end; i--)
-                                list << QString::number(i);
+                                list << ProString(QString::number(i), NoHash);
                         }
                     }
                 }
@@ -1309,19 +1319,19 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProLoop(ProLoop *loop)
     forever {
         if (infinite) {
             if (!variable.isEmpty())
-                m_valuemapStack.top()[variable] = QStringList(QString::number(index++));
+                m_valuemapStack.top()[variable] = ProStringList(ProString(QString::number(index++), NoHash));
             if (index > 1000) {
                 errorMessage(format("ran into infinite loop (> 1000 iterations)."));
                 break;
             }
         } else {
-            QString val;
+            ProString val;
             do {
                 if (index >= list.count())
                     goto do_break;
                 val = list.at(index++);
             } while (val.isEmpty()); // stupid, but qmake is like that
-            m_valuemapStack.top()[variable] = QStringList(val);
+            m_valuemapStack.top()[variable] = ProStringList(val);
         }
 
         ret = visitProBlock(loop->items());
@@ -1350,12 +1360,13 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProLoop(ProLoop *loop)
 void ProFileEvaluator::Private::visitProVariable(ProVariable *var)
 {
     m_lineNo = var->lineNumber();
-    const QString &varName = var->variable();
+    const ProString &varName = var->variable();
 
     if (var->variableOperator() == ProVariable::ReplaceOperator) {      // ~=
         // DEFINES ~= s/a/b/?[gqi]
 
-        QString val = expandVariableReferences(var->value(), 0, true).first();
+        const ProStringList &varVal = expandVariableReferences(var->value(), 0, true);
+        const QString &val = varVal.at(0).toQString(m_tmp1);
         if (val.length() < 4 || val.at(0) != QLatin1Char('s')) {
             logMessage(format("the ~= operator can handle only the s/// function."));
             return;
@@ -1383,11 +1394,11 @@ void ProFileEvaluator::Private::visitProVariable(ProVariable *var)
         if (!m_skipLevel || m_cumulative) {
             // We could make a union of modified and unmodified values,
             // but this will break just as much as it fixes, so leave it as is.
-            replaceInList(&valuesRef(varName), regexp, replace, global);
-            replaceInList(&m_filevaluemap[currentProFile()][varName], regexp, replace, global);
+            replaceInList(&valuesRef(varName), regexp, replace, global, m_tmp2);
+            replaceInList(&m_filevaluemap[currentProFile()][varName], regexp, replace, global, m_tmp2);
         }
     } else {
-        QStringList varVal = expandVariableReferences(var->value());
+        const ProStringList &varVal = expandVariableReferences(var->value());
         switch (var->variableOperator()) {
         default: // ReplaceOperator - cannot happen
         case ProVariable::SetOperator:          // =
@@ -1434,8 +1445,9 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProCondition(ProCondition
         if (!m_cumulative && m_skipLevel)
             return ProItem::ReturnTrue;
         int lparen = cond->text().indexOf(QLatin1Char('('));
-        QString arguments = cond->text().mid(lparen + 1, cond->text().length() - lparen - 2);
-        QString funcName = cond->text().left(lparen).trimmed();
+        ProString text(cond->text());
+        ProString arguments = text.mid(lparen + 1, text.size() - lparen - 2);
+        ProString funcName = text.left(lparen).trimmed();
         m_lineNo = cond->lineNumber();
         return evaluateConditionalFunction(funcName, arguments);
     } else {
@@ -1475,12 +1487,12 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProFile(ProFile *pro)
                 }
                 if (!qmake_cache.isEmpty()) {
                     qmake_cache = resolvePath(qmake_cache);
-                    QHash<QString, QStringList> cache_valuemap;
+                    QHash<ProString, ProStringList> cache_valuemap;
                     if (evaluateFileInto(qmake_cache, &cache_valuemap, 0)) {
                         if (m_option->qmakespec.isEmpty()) {
-                            const QStringList &vals = cache_valuemap.value(QLatin1String("QMAKESPEC"));
+                            const ProStringList &vals = cache_valuemap.value(ProString("QMAKESPEC"));
                             if (!vals.isEmpty())
-                                m_option->qmakespec = vals.first();
+                                m_option->qmakespec = vals.first().toQString();
                         }
                     } else {
                         qmake_cache.clear();
@@ -1571,14 +1583,15 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProFile(ProFile *pro)
             refFunctions(&m_functionDefs.testFunctions);
             refFunctions(&m_functionDefs.replaceFunctions);
 
-            QStringList &tgt = m_valuemapStack.top()[QLatin1String("TARGET")];
+            ProStringList &tgt = m_valuemapStack.top()[ProString("TARGET")];
             if (tgt.isEmpty())
-                tgt.append(QFileInfo(pro->fileName()).baseName());
+                tgt.append(ProString(QFileInfo(pro->fileName()).baseName(), NoHash));
 
-            QStringList &tmp = m_valuemapStack.top()[QLatin1String("CONFIG")];
-            tmp.append(m_addUserConfigCmdArgs);
+            ProStringList &tmp = m_valuemapStack.top()[ProString("CONFIG")];
+            foreach (const QString &add, m_addUserConfigCmdArgs)
+                tmp.append(ProString(add, NoHash));
             foreach (const QString &remove, m_removeUserConfigCmdArgs)
-                tmp.removeAll(remove);
+                removeAll(&tmp, ProString(remove, NoHash));
         }
     }
 
@@ -1591,10 +1604,11 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProFile(ProFile *pro)
             QSet<QString> processed;
             forever {
                 bool finished = true;
-                QStringList configs = valuesDirect(statics.strCONFIG);
+                ProStringList configs = valuesDirect(statics.strCONFIG);
                 for (int i = configs.size() - 1; i >= 0; --i) {
-                    const QString config = configs.at(i).toLower();
+                    QString config = configs.at(i).toQString(m_tmp1).toLower();
                     if (!processed.contains(config)) {
+                        config.detach();
                         processed.insert(config);
                         if (evaluateFeatureFile(config)) {
                             finished = false;
@@ -1758,8 +1772,9 @@ QString ProFileEvaluator::Private::currentDirectory() const
 #endif
 
 // The (QChar*)current->constData() constructs below avoid pointless detach() calls
+// FIXME: This is inefficient. Should not make new string if it is a straight subsegment
 static inline void ALWAYS_INLINE appendChar(ushort unicode,
-    QString *current, QChar **ptr, QString *pending)
+    QString *current, QChar **ptr, ProString *pending)
 {
     if (!pending->isEmpty()) {
         int len = pending->size();
@@ -1771,8 +1786,8 @@ static inline void ALWAYS_INLINE appendChar(ushort unicode,
     *(*ptr)++ = QChar(unicode);
 }
 
-static void appendString(const QString &string,
-    QString *current, QChar **ptr, QString *pending)
+static void appendString(const ProString &string,
+    QString *current, QChar **ptr, ProString *pending)
 {
     if (string.isEmpty())
         return;
@@ -1791,47 +1806,47 @@ static void appendString(const QString &string,
         return;
     }
     *ptr = (QChar*)current->constData() + len;
-    ::memcpy(*ptr, string.data(), string.size() * 2);
+    ::memcpy(*ptr, string.constData(), string.size() * 2);
     *ptr += string.size();
 }
 
-static void flushCurrent(QStringList *ret,
-    QString *current, QChar **ptr, QString *pending, bool joined)
+static void flushCurrent(ProStringList *ret,
+    QString *current, QChar **ptr, ProString *pending, bool joined)
 {
     QChar *uc = (QChar*)current->constData();
     int len = *ptr - uc;
     if (len) {
-        ret->append(QString(uc, len));
+        ret->append(ProString(QString(uc, len), NoHash));
         *ptr = uc;
     } else if (!pending->isEmpty()) {
         ret->append(*pending);
         pending->clear();
     } else if (joined) {
-        ret->append(QString());
+        ret->append(ProString());
     }
 }
 
-static inline void flushFinal(QStringList *ret,
-    const QString &current, const QChar *ptr, const QString &pending,
-    const QString &str, bool replaced, bool joined)
+static inline void flushFinal(ProStringList *ret,
+    const QString &current, const QChar *ptr, const ProString &pending,
+    const ProString &str, bool replaced, bool joined)
 {
     int len = ptr - current.data();
     if (len) {
         if (!replaced && len == str.size())
             ret->append(str);
         else
-            ret->append(QString(current.data(), len));
+            ret->append(ProString(QString(current.data(), len), NoHash));
     } else if (!pending.isEmpty()) {
         ret->append(pending);
     } else if (joined) {
-        ret->append(QString());
+        ret->append(ProString());
     }
 }
 
-QStringList ProFileEvaluator::Private::expandVariableReferences(
-    const QString &str, int *pos, bool joined)
+ProStringList ProFileEvaluator::Private::expandVariableReferences(
+    const ProString &str, int *pos, bool joined)
 {
-    QStringList ret;
+    ProStringList ret;
 //    if (ok)
 //        *ok = true;
     if (str.isEmpty() && !pos)
@@ -1854,17 +1869,17 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(
     const ushort DOUBLEQUOTE = '"';
 
     ushort unicode, quote = 0, parens = 0;
-    const ushort *str_data = (const ushort *)str.data();
-    const int str_len = str.length();
+    const ushort *str_data = (const ushort *)str.constData();
+    const int str_len = str.size();
 
-    QString var, args;
+    ProString var, args;
 
     bool replaced = false;
     bool putSpace = false;
     QString current; // Buffer for successively assembled string segments
     current.resize(str.size());
     QChar *ptr = current.data();
-    QString pending; // Buffer for string segments from variables
+    ProString pending; // Buffer for string segments from variables
     // Only one of the above buffers can be filled at a given time.
     for (int i = pos ? *pos : 0; i < str_len; ++i) {
         unicode = str_data[i];
@@ -1900,7 +1915,7 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(
                     unicode = str_data[i];
                     // at this point, i points to either the 'term' or 'next' character (which is in unicode)
                 }
-                var = QString::fromRawData((QChar*)str_data + name_start, i - name_start);
+                var = str.mid(name_start, i - name_start);
                 if (var_type == VAR && unicode == LPAREN) {
                     var_type = FUNCTION;
                     name_start = i + 1;
@@ -1917,7 +1932,7 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(
                             --depth;
                         }
                     }
-                    args = QString((QChar*)str_data + name_start, i - name_start);
+                    args = str.mid(name_start, i - name_start);
                     if (++i < str_len)
                         unicode = str_data[i];
                     else
@@ -1934,20 +1949,21 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(
 //                            *ok = false;
                         if (pos)
                             *pos = str_len;
-                        return QStringList();
+                        return ProStringList();
                     }
                 } else {
                     // move the 'cursor' back to the last char of the thing we were looking at
                     --i;
                 }
 
-                QStringList replacement;
+                ProStringList replacement;
                 if (var_type == ENVIRON) {
-                    replacement = split_value_list(QString::fromLocal8Bit(qgetenv(var.toLatin1().constData())));
+                    replacement = split_value_list(QString::fromLocal8Bit(qgetenv(
+                            var.toQString(m_tmp1).toLatin1().constData())));
                 } else if (var_type == PROPERTY) {
-                    replacement << propertyValue(var);
+                    replacement << ProString(propertyValue(var.toQString(m_tmp1)), NoHash);
                 } else if (var_type == FUNCTION) {
-                    replacement << evaluateExpandFunction(var, args);
+                    replacement += evaluateExpandFunction(var, args);
                 } else if (var_type == VAR) {
                     replacement = values(map(var));
                 }
@@ -1958,7 +1974,7 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(
                             if (!replacement.at(0).isEmpty()) // Bizarre, indeed
                                 appendChar(' ', &current, &ptr, &pending);
                         }
-                        appendString(replacement.join(statics.field_sep),
+                        appendString(ProString(replacement.join(statics.field_sep), NoHash),
                                      &current, &ptr, &pending);
                     } else {
                         appendString(replacement.at(0), &current, &ptr, &pending);
@@ -2056,15 +2072,19 @@ bool ProFileEvaluator::Private::isActiveConfig(const QString &config, bool regex
         return true;
 
     if (regex && (config.contains(QLatin1Char('*')) || config.contains(QLatin1Char('?')))) {
-        QRegExp re(config, Qt::CaseSensitive, QRegExp::Wildcard);
+        QString cfg = config;
+        cfg.detach(); // Keep m_tmp out of QRegExp's cache
+        QRegExp re(cfg, Qt::CaseSensitive, QRegExp::Wildcard);
 
         if (re.exactMatch(m_option->qmakespec_name))
             return true;
 
         // CONFIG variable
-        foreach (const QString &configValue, valuesDirect(statics.strCONFIG)) {
-            if (re.exactMatch(configValue))
+        int t = 0;
+        foreach (const ProString &configValue, valuesDirect(statics.strCONFIG)) {
+            if (re.exactMatch(configValue.toQString(m_tmp[t])))
                 return true;
+            t ^= 1;
         }
     } else {
         // mkspecs
@@ -2072,39 +2092,39 @@ bool ProFileEvaluator::Private::isActiveConfig(const QString &config, bool regex
             return true;
 
         // CONFIG variable
-        if (valuesDirect(statics.strCONFIG).contains(config))
+        if (valuesDirect(statics.strCONFIG).contains(ProString(config, NoHash)))
             return true;
     }
 
     return false;
 }
 
-QList<QStringList> ProFileEvaluator::Private::prepareFunctionArgs(const QString &arguments)
+QList<ProStringList> ProFileEvaluator::Private::prepareFunctionArgs(const ProString &arguments)
 {
-    QList<QStringList> args_list;
-    for (int pos = 0; pos < arguments.length(); )
+    QList<ProStringList> args_list;
+    for (int pos = 0; pos < arguments.size(); )
         args_list << expandVariableReferences(arguments, &pos);
     return args_list;
 }
 
-QStringList ProFileEvaluator::Private::evaluateFunction(
-        ProFunctionDef *funcPtr, const QList<QStringList> &argumentsList, bool *ok)
+ProStringList ProFileEvaluator::Private::evaluateFunction(
+        ProFunctionDef *funcPtr, const QList<ProStringList> &argumentsList, bool *ok)
 {
     bool oki;
-    QStringList ret;
+    ProStringList ret;
 
     if (m_valuemapStack.count() >= 100) {
         errorMessage(format("ran into infinite recursion (depth > 100)."));
         oki = false;
     } else {
-        m_valuemapStack.push(QHash<QString, QStringList>());
+        m_valuemapStack.push(QHash<ProString, ProStringList>());
         int loopLevel = m_loopLevel;
         m_loopLevel = 0;
 
-        QStringList args;
+        ProStringList args;
         for (int i = 0; i < argumentsList.count(); ++i) {
             args += argumentsList[i];
-            m_valuemapStack.top()[QString::number(i+1)] = argumentsList[i];
+            m_valuemapStack.top()[ProString(QString::number(i+1))] = argumentsList[i];
         }
         m_valuemapStack.top()[statics.strARGS] = args;
         oki = (visitProBlock(funcPtr->items()) != ProItem::ReturnFalse); // True || Return
@@ -2118,44 +2138,47 @@ QStringList ProFileEvaluator::Private::evaluateFunction(
         *ok = oki;
     if (oki)
         return ret;
-    return QStringList();
+    return ProStringList();
 }
 
-QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &func, const QString &arguments)
+ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
+        const ProString &func, const ProString &arguments)
 {
     if (ProFunctionDef *funcPtr = m_functionDefs.replaceFunctions.value(func, 0))
         return evaluateFunction(funcPtr, prepareFunctionArgs(arguments), 0);
 
     //why don't the builtin functions just use args_list? --Sam
     int pos = 0;
-    QStringList args = expandVariableReferences(arguments, &pos, true);
+    ProStringList args = expandVariableReferences(arguments, &pos, true);
 
-    ExpandFunc func_t = ExpandFunc(statics.expands.value(func.toLower()));
+    ExpandFunc func_t = ExpandFunc(statics.expands.value(func.toQString(m_tmp1).toLower()));
 
-    QStringList ret;
+    ProStringList ret;
 
     switch (func_t) {
         case E_BASENAME:
         case E_DIRNAME:
         case E_SECTION: {
             bool regexp = false;
-            QString sep, var;
+            QString sep;
+            ProString var;
             int beg = 0;
             int end = -1;
             if (func_t == E_SECTION) {
                 if (args.count() != 3 && args.count() != 4) {
                     logMessage(format("%1(var) section(var, sep, begin, end) "
-                        "requires three or four arguments.").arg(func));
+                        "requires three or four arguments.").arg(func.toQString(m_tmp1)));
                 } else {
                     var = args[0];
-                    sep = args[1];
-                    beg = args[2].toInt();
+                    sep = args.at(1).toQString();
+                    beg = args.at(2).toQString(m_tmp2).toInt();
                     if (args.count() == 4)
-                        end = args[3].toInt();
+                        end = args.at(3).toQString(m_tmp2).toInt();
                 }
             } else {
                 if (args.count() != 1) {
-                    logMessage(format("%1(var) requires one argument.").arg(func));
+                    logMessage(format("%1(var) requires one argument.")
+                               .arg(func.toQString(m_tmp1)));
                 } else {
                     var = args[0];
                     regexp = true;
@@ -2166,14 +2189,18 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                         beg = -1;
                 }
             }
-            if (!var.isNull()) {
+            if (!var.isEmpty()) {
                 if (regexp) {
                     QRegExp sepRx(sep);
-                    foreach (const QString &str, values(map(var)))
-                        ret += str.section(sepRx, beg, end);
+                    foreach (const ProString &str, values(map(var))) {
+                        const QString &rstr = str.toQString(m_tmp1).section(sepRx, beg, end);
+                        ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr, NoHash));
+                    }
                 } else {
-                    foreach (const QString &str, values(map(var)))
-                        ret += str.section(sep, beg, end);
+                    foreach (const ProString &str, values(map(var))) {
+                        const QString &rstr = str.toQString(m_tmp1).section(sep, beg, end);
+                        ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr, NoHash));
+                    }
                 }
             }
             break;
@@ -2182,9 +2209,10 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
             if(args.count() < 1) {
                 logMessage(format("sprintf(format, ...) requires at least one argument"));
             } else {
-                QString tmp = args.at(0);
+                QString tmp = args.at(0).toQString(m_tmp1);
                 for (int i = 1; i < args.count(); ++i)
-                    tmp = tmp.arg(args.at(i));
+                    tmp = tmp.arg(args.at(i).toQString(m_tmp2));
+                // Note: this depends on split_value_list() making a deep copy
                 ret = split_value_list(tmp);
             }
             break;
@@ -2192,16 +2220,17 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
             if (args.count() < 1 || args.count() > 4) {
                 logMessage(format("join(var, glue, before, after) requires one to four arguments."));
             } else {
-                QString glue, before, after;
+                QString glue;
+                ProString before, after;
                 if (args.count() >= 2)
-                    glue = args[1];
+                    glue = args.at(1).toQString(m_tmp1);
                 if (args.count() >= 3)
                     before = args[2];
                 if (args.count() == 4)
                     after = args[3];
-                const QStringList &var = values(map(args.first()));
+                const ProStringList &var = values(map(args.at(0)));
                 if (!var.isEmpty())
-                    ret.append(before + var.join(glue) + after);
+                    ret.append(ProString(before + var.join(glue) + after, NoHash));
             }
             break;
         }
@@ -2209,10 +2238,10 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
             if (args.count() != 2) {
                 logMessage(format("split(var, sep) requires one or two arguments"));
             } else {
-                const QString &sep = (args.count() == 2) ? args[1] : statics.field_sep;
-                foreach (const QString &var, values(map(args.first())))
-                    foreach (const QString &splt, var.split(sep))
-                        ret.append(splt);
+                const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep;
+                foreach (const ProString &var, values(map(args.at(0))))
+                    foreach (const QString &splt, var.toQString(m_tmp2).split(sep))
+                        ret << (splt.isSharedWith(m_tmp2) ? var : ProString(splt, NoHash));
             }
             break;
         case E_MEMBER:
@@ -2220,10 +2249,10 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                 logMessage(format("member(var, start, end) requires one to three arguments."));
             } else {
                 bool ok = true;
-                const QStringList &var = values(map(args.first()));
+                const ProStringList &var = values(map(args.at(0)));
                 int start = 0, end = 0;
                 if (args.count() >= 2) {
-                    QString start_str = args[1];
+                    const QString &start_str = args.at(1).toQString(m_tmp1);
                     start = start_str.toInt(&ok);
                     if (!ok) {
                         if (args.count() == 2) {
@@ -2240,10 +2269,10 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                     } else {
                         end = start;
                         if (args.count() == 3)
-                            end = args[2].toInt(&ok);
+                            end = args.at(2).toQString(m_tmp1).toInt(&ok);
                         if (!ok)
                             logMessage(format("member() argument 3 (end) '%2' invalid.\n")
-                                .arg(args[2]));
+                                .arg(args.at(2).toQString(m_tmp1)));
                     }
                 }
                 if (ok) {
@@ -2266,9 +2295,9 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
         case E_FIRST:
         case E_LAST:
             if (args.count() != 1) {
-                logMessage(format("%1(var) requires one argument.").arg(func));
+                logMessage(format("%1(var) requires one argument.").arg(func.toQString(m_tmp1)));
             } else {
-                const QStringList var = values(map(args.first()));
+                const ProStringList &var = values(map(args.at(0)));
                 if (!var.isEmpty()) {
                     if (func_t == E_FIRST)
                         ret.append(var[0]);
@@ -2281,17 +2310,17 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
             if(args.count() != 1)
                 logMessage(format("size(var) requires one argument."));
             else
-                ret.append(QString::number(values(map(args.at(0))).size()));
+                ret.append(ProString(QString::number(values(map(args.at(0))).size()), NoHash));
             break;
         case E_CAT:
             if (args.count() < 1 || args.count() > 2) {
                 logMessage(format("cat(file, singleline=true) requires one or two arguments."));
             } else {
-                QString file = args[0];
+                const QString &file = args.at(0).toQString(m_tmp1);
 
                 bool singleLine = true;
                 if (args.count() > 1)
-                    singleLine = isTrue(args.at(1));
+                    singleLine = isTrue(args.at(1), m_tmp2);
 
                 QFile qfile(resolvePath(expandEnvVars(file)));
                 if (qfile.open(QIODevice::ReadOnly)) {
@@ -2299,7 +2328,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                     while (!stream.atEnd()) {
                         ret += split_value_list(stream.readLine().trimmed());
                         if (!singleLine)
-                            ret += QLatin1String("\n");
+                            ret += ProString("\n", NoHash);
                     }
                     qfile.close();
                 }
@@ -2309,9 +2338,9 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
             if (args.count() != 2) {
                 logMessage(format("fromfile(file, variable) requires two arguments."));
             } else {
-                QHash<QString, QStringList> vars;
-                if (evaluateFileInto(resolvePath(expandEnvVars(args.at(0))), &vars, 0))
-                    ret = vars.value(args.at(1));
+                QHash<ProString, ProStringList> vars;
+                if (evaluateFileInto(resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))), &vars, 0))
+                    ret = vars.value(map(args.at(1)));
             }
             break;
         case E_EVAL:
@@ -2324,20 +2353,23 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
         case E_LIST: {
             QString tmp;
             tmp.sprintf(".QMAKE_INTERNAL_TMP_variableName_%d", m_listCount++);
-            ret = QStringList(tmp);
-            QStringList lst;
-            foreach (const QString &arg, args)
-                lst += split_value_list(arg);
-            m_valuemapStack.top()[tmp] = lst;
+            ret = ProStringList(ProString(tmp, NoHash));
+            ProStringList lst;
+            foreach (const ProString &arg, args)
+                lst += split_value_list(arg.toQString(m_tmp1)); // Relies on deep copy
+            m_valuemapStack.top()[ret.at(0)] = lst;
             break; }
         case E_FIND:
             if (args.count() != 2) {
                 logMessage(format("find(var, str) requires two arguments."));
             } else {
-                QRegExp regx(args[1]);
-                foreach (const QString &val, values(map(args.first())))
-                    if (regx.indexIn(val) != -1)
+                QRegExp regx(args.at(1).toQString());
+                int t = 0;
+                foreach (const ProString &val, values(map(args.at(0)))) {
+                    if (regx.indexIn(val.toQString(m_tmp[t])) != -1)
                         ret += val;
+                    t ^= 1;
+                }
             }
             break;
         case E_SYSTEM:
@@ -2351,7 +2383,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                                            + QLatin1String(" && ") + args[0]).toLatin1(), "r");
                     bool singleLine = true;
                     if (args.count() > 1)
-                        singleLine = isTrue(args.at(1));
+                        singleLine = isTrue(args.at(1), m_tmp2);
                     QString output;
                     while (proc && !feof(proc)) {
                         int read_in = int(fread(buff, 1, 255, proc));
@@ -2374,7 +2406,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
             if(args.count() != 1) {
                 logMessage(format("unique(var) requires one argument."));
             } else {
-                ret = values(map(args.first()));
+                ret = values(map(args.at(0)));
                 ret.removeDuplicates();
             }
             break;
@@ -2383,8 +2415,9 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
             break;
         case E_ESCAPE_EXPAND:
             for (int i = 0; i < args.size(); ++i) {
-                QChar *i_data = args[i].data();
-                int i_len = args[i].length();
+                QString str = args.at(i).toQString();
+                QChar *i_data = str.data();
+                int i_len = str.length();
                 for (int x = 0; x < i_len; ++x) {
                     if (*(i_data+x) == QLatin1Char('\\') && x < i_len-1) {
                         if (*(i_data+x+1) == QLatin1Char('\\')) {
@@ -2410,20 +2443,22 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                         }
                     }
                 }
-                ret.append(QString(i_data, i_len));
+                ret.append(ProString(QString(i_data, i_len), NoHash));
             }
             break;
         case E_RE_ESCAPE:
-            for (int i = 0; i < args.size(); ++i)
-                ret += QRegExp::escape(args[i]);
+            for (int i = 0; i < args.size(); ++i) {
+                const QString &rstr = QRegExp::escape(args.at(i).toQString(m_tmp1));
+                ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr, NoHash));
+            }
             break;
         case E_UPPER:
         case E_LOWER:
-            for (int i = 0; i < args.count(); ++i)
-                if (func_t == E_UPPER)
-                    ret += args[i].toUpper();
-                else
-                    ret += args[i].toLower();
+            for (int i = 0; i < args.count(); ++i) {
+                QString rstr = args.at(i).toQString(m_tmp1);
+                rstr = (func_t == E_UPPER) ? rstr.toUpper() : rstr.toLower();
+                ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr, NoHash));
+            }
             break;
         case E_FILES:
             if (args.count() != 1 && args.count() != 2) {
@@ -2431,9 +2466,9 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
             } else {
                 bool recursive = false;
                 if (args.count() == 2)
-                    recursive = isTrue(args.at(1));
+                    recursive = isTrue(args.at(1), m_tmp2);
                 QStringList dirs;
-                QString r = fixPathToLocalOS(args[0]);
+                QString r = fixPathToLocalOS(args.at(0).toQString(m_tmp1));
                 QString pfx;
                 if (IoUtils::isRelativePath(r)) {
                     pfx = currentDirectory();
@@ -2448,6 +2483,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                     dirs.append(QString());
                 }
 
+                r.detach(); // Keep m_tmp out of QRegExp's cache
                 const QRegExp regex(r, Qt::CaseSensitive, QRegExp::Wildcard);
                 for (int d = 0; d < dirs.count(); d++) {
                     QString dir = dirs[d];
@@ -2461,7 +2497,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
                                 dirs.append(fname + QDir::separator());
                         }
                         if (regex.exactMatch(qdir[i]))
-                            ret += fname;
+                            ret += ProString(fname, NoHash);
                     }
                 }
             }
@@ -2470,17 +2506,22 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
             if(args.count() != 3 ) {
                 logMessage(format("replace(var, before, after) requires three arguments"));
             } else {
-                const QRegExp before(args[1]);
-                const QString after(args[2]);
-                foreach (QString val, values(map(args.first())))
-                    ret += val.replace(before, after);
+                const QRegExp before(args.at(1).toQString());
+                const QString &after(args.at(2).toQString(m_tmp2));
+                foreach (const ProString &val, values(map(args.at(0)))) {
+                    QString rstr = val.toQString(m_tmp1);
+                    QString copy = rstr; // Force a detach on modify
+                    rstr.replace(before, after);
+                    ret << (rstr.isSharedWith(m_tmp1) ? val : ProString(rstr, NoHash));
+                }
             }
             break;
         case 0:
-            logMessage(format("'%1' is not a recognized replace function").arg(func));
+            logMessage(format("'%1' is not a recognized replace function")
+                       .arg(func.toQString(m_tmp1)));
             break;
         default:
-            logMessage(format("Function '%1' is not implemented").arg(func));
+            logMessage(format("Function '%1' is not implemented").arg(func.toQString(m_tmp1)));
             break;
     }
 
@@ -2488,27 +2529,28 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
 }
 
 ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
-        const QString &function, const QString &arguments)
+        const ProString &function, const ProString &arguments)
 {
     if (ProFunctionDef *funcPtr = m_functionDefs.testFunctions.value(function, 0)) {
         bool ok;
-        QStringList ret = evaluateFunction(funcPtr, prepareFunctionArgs(arguments), &ok);
+        ProStringList ret = evaluateFunction(funcPtr, prepareFunctionArgs(arguments), &ok);
         if (ok) {
             if (ret.isEmpty()) {
                 return ProItem::ReturnTrue;
             } else {
-                if (ret.first() != statics.strfalse) {
-                    if (ret.first() == statics.strtrue) {
+                if (ret.at(0) != statics.strfalse) {
+                    if (ret.at(0) == statics.strtrue) {
                         return ProItem::ReturnTrue;
                     } else {
                         bool ok;
-                        int val = ret.first().toInt(&ok);
+                        int val = ret.at(0).toQString(m_tmp1).toInt(&ok);
                         if (ok) {
                             if (val)
                                 return ProItem::ReturnTrue;
                         } else {
                             logMessage(format("Unexpected return value from test '%1': %2")
-                                          .arg(function).arg(ret.join(QLatin1String(" :: "))));
+                                          .arg(function.toQString(m_tmp1))
+                                          .arg(ret.join(QLatin1String(" :: "))));
                         }
                     }
                 }
@@ -2519,7 +2561,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
 
     //why don't the builtin functions just use args_list? --Sam
     int pos = 0;
-    QStringList args = expandVariableReferences(arguments, &pos, true);
+    ProStringList args = expandVariableReferences(arguments, &pos, true);
 
     TestFunc func_t = (TestFunc)statics.functions.value(function);
 
@@ -2536,7 +2578,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 else if (args[1] == QLatin1String("replace"))
                     return returnBool(m_functionDefs.replaceFunctions.contains(args[0]));
                 logMessage(format("defined(function, type):"
-                                     " unexpected type [%1].\n").arg(args[1]));
+                                  " unexpected type [%1].\n").arg(args.at(1).toQString(m_tmp1)));
                 return ProItem::ReturnFalse;
             }
             return returnBool(m_functionDefs.replaceFunctions.contains(args[0])
@@ -2559,13 +2601,13 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 logMessage(format("export(variable) requires one argument."));
                 return ProItem::ReturnFalse;
             }
-            const QString &var = map(args.at(0));
+            const ProString &var = map(args.at(0));
             for (int i = m_valuemapStack.size(); --i > 0; ) {
-                QHash<QString, QStringList>::Iterator it = m_valuemapStack[i].find(var);
+                QHash<ProString, ProStringList>::Iterator it = m_valuemapStack[i].find(var);
                 if (it != m_valuemapStack.at(i).end()) {
                     if (it->constBegin() == statics.fakeValue.constBegin()) {
                         // This is stupid, but qmake doesn't propagate deletions
-                        m_valuemapStack[0][var] = QStringList();
+                        m_valuemapStack[0][var] = ProStringList();
                     } else {
                         m_valuemapStack[0][var] = *it;
                     }
@@ -2581,18 +2623,24 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
             if (args.count() < 2 || args.count() > 3) {
                 logMessage(format("infile(file, var, [values]) requires two or three arguments."));
             } else {
-                QHash<QString, QStringList> vars;
-                if (!evaluateFileInto(resolvePath(expandEnvVars(args.at(0))), &vars, 0))
+                QHash<ProString, ProStringList> vars;
+                if (!evaluateFileInto(resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))), &vars, 0))
                     return ProItem::ReturnFalse;
                 if (args.count() == 2)
                     return returnBool(vars.contains(args.at(1)));
                 QRegExp regx;
-                const QString &qry = args.at(2);
-                if (qry != QRegExp::escape(qry))
-                    regx.setPattern(qry);
-                foreach (const QString &s, vars.value(args.at(1)))
-                    if ((!regx.isEmpty() && regx.exactMatch(s)) || s == qry)
+                const QString &qry = args.at(2).toQString(m_tmp1);
+                if (qry != QRegExp::escape(qry)) {
+                    QString copy = qry;
+                    copy.detach();
+                    regx.setPattern(copy);
+                }
+                int t = 0;
+                foreach (const ProString &s, vars.value(map(args.at(1)))) {
+                    if ((!regx.isEmpty() && regx.exactMatch(s.toQString(m_tmp[t]))) || s == qry)
                         return ProItem::ReturnTrue;
+                    t ^= 1;
+                }
             }
             return ProItem::ReturnFalse;
 #if 0
@@ -2628,7 +2676,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 logMessage(format("if(condition) requires one argument."));
                 return ProItem::ReturnFalse;
             }
-            QString cond = args.first();
+            const ProString &cond = args.at(0);
             bool quoted = false;
             bool ret = true;
             bool orOp = false;
@@ -2639,8 +2687,8 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
             test.reserve(20);
             QString args;
             args.reserve(50);
-            const QChar *d = cond.unicode();
-            const QChar *ed = d + cond.length();
+            const QChar *d = cond.constData();
+            const QChar *ed = d + cond.size();
             while (d < ed) {
                 ushort c = (d++)->unicode();
                 bool isOp = false;
@@ -2675,7 +2723,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 if (!quoted && !parens && (isOp || d == ed)) {
                     if (m_cumulative || (orOp != ret)) {
                         if (isFunc)
-                            ret = evaluateConditionalFunction(test, args);
+                            ret = evaluateConditionalFunction(ProString(test), ProString(args, NoHash));
                         else
                             ret = isActiveConfig(test, true);
                         ret ^= invert;
@@ -2695,9 +2743,9 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 return ProItem::ReturnFalse;
             }
             if (args.count() == 1)
-                return returnBool(isActiveConfig(args.first()));
-            const QStringList mutuals = args[1].split(QLatin1Char('|'));
-            const QStringList &configs = valuesDirect(statics.strCONFIG);
+                return returnBool(isActiveConfig(args.at(0).toQString(m_tmp2)));
+            const QStringList &mutuals = args.at(1).toQString(m_tmp2).split(QLatin1Char('|'));
+            const ProStringList &configs = valuesDirect(statics.strCONFIG);
 
             for (int i = configs.size() - 1; i >= 0; i--) {
                 for (int mut = 0; mut < mutuals.count(); mut++) {
@@ -2714,24 +2762,30 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 return ProItem::ReturnFalse;
             }
 
-            const QString &qry = args.at(1);
+            const QString &qry = args.at(1).toQString(m_tmp1);
             QRegExp regx;
-            if (qry != QRegExp::escape(qry))
-                regx.setPattern(qry);
-            const QStringList &l = values(map(args.first()));
+            if (qry != QRegExp::escape(qry)) {
+                QString copy = qry;
+                copy.detach();
+                regx.setPattern(copy);
+            }
+            const ProStringList &l = values(map(args.at(0)));
             if (args.count() == 2) {
+                int t = 0;
                 for (int i = 0; i < l.size(); ++i) {
-                    const QString val = l[i];
-                    if ((!regx.isEmpty() && regx.exactMatch(val)) || val == qry)
+                    const ProString &val = l[i];
+                    if ((!regx.isEmpty() && regx.exactMatch(val.toQString(m_tmp[t]))) || val == qry)
                         return ProItem::ReturnTrue;
+                    t ^= 1;
                 }
             } else {
-                const QStringList mutuals = args[2].split(QLatin1Char('|'));
+                const QStringList &mutuals = args.at(2).toQString(m_tmp3).split(QLatin1Char('|'));
                 for (int i = l.size() - 1; i >= 0; i--) {
-                    const QString val = l[i];
+                    const ProString val = l[i];
                     for (int mut = 0; mut < mutuals.count(); mut++) {
                         if (val == mutuals[mut].trimmed()) {
-                            return returnBool((!regx.isEmpty() && regx.exactMatch(val))
+                            return returnBool((!regx.isEmpty()
+                                               && regx.exactMatch(val.toQString(m_tmp2)))
                                               || val == qry);
                         }
                     }
@@ -2744,34 +2798,38 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 logMessage(format("count(var, count, op=\"equals\") requires two or three arguments."));
                 return ProItem::ReturnFalse;
             }
-            int cnt = values(map(args.first())).count();
+            int cnt = values(map(args.at(0))).count();
             if (args.count() == 3) {
-                QString comp = args[2];
+                const ProString &comp = args.at(2);
+                const int val = args.at(1).toQString(m_tmp1).toInt();
                 if (comp == QLatin1String(">") || comp == QLatin1String("greaterThan")) {
-                    return returnBool(cnt > args[1].toInt());
+                    return returnBool(cnt > val);
                 } else if (comp == QLatin1String(">=")) {
-                    return returnBool(cnt >= args[1].toInt());
+                    return returnBool(cnt >= val);
                 } else if (comp == QLatin1String("<") || comp == QLatin1String("lessThan")) {
-                    return returnBool(cnt < args[1].toInt());
+                    return returnBool(cnt < val);
                 } else if (comp == QLatin1String("<=")) {
-                    return returnBool(cnt <= args[1].toInt());
+                    return returnBool(cnt <= val);
                 } else if (comp == QLatin1String("equals") || comp == QLatin1String("isEqual")
                            || comp == QLatin1String("=") || comp == QLatin1String("==")) {
-                    return returnBool(cnt == args[1].toInt());
+                    return returnBool(cnt == val);
                 } else {
-                    logMessage(format("unexpected modifier to count(%2)").arg(comp));
+                    logMessage(format("unexpected modifier to count(%2)")
+                               .arg(comp.toQString(m_tmp1)));
                     return ProItem::ReturnFalse;
                 }
             }
-            return returnBool(cnt == args[1].toInt());
+            return returnBool(cnt == args.at(1).toQString(m_tmp1).toInt());
         }
         case T_GREATERTHAN:
         case T_LESSTHAN: {
             if (args.count() != 2) {
-                logMessage(format("%1(variable, value) requires two arguments.").arg(function));
+                logMessage(format("%1(variable, value) requires two arguments.")
+                           .arg(function.toQString(m_tmp1)));
                 return ProItem::ReturnFalse;
             }
-            QString rhs(args[1]), lhs(values(map(args.at(0))).join(statics.field_sep));
+            const QString &rhs(args.at(1).toQString(m_tmp1)),
+                          &lhs(values(map(args.at(0))).join(statics.field_sep));
             bool ok;
             int rhs_int = rhs.toInt(&ok);
             if (ok) { // do integer compare
@@ -2788,20 +2846,23 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
         }
         case T_EQUALS:
             if (args.count() != 2) {
-                logMessage(format("%1(variable, value) requires two arguments.").arg(function));
+                logMessage(format("%1(variable, value) requires two arguments.")
+                           .arg(function.toQString(m_tmp1)));
                 return ProItem::ReturnFalse;
             }
-            return returnBool(values(map(args.at(0))).join(statics.field_sep) == args.at(1));
+            return returnBool(values(map(args.at(0))).join(statics.field_sep)
+                              == args.at(1).toQString(m_tmp1));
         case T_CLEAR: {
             if (m_skipLevel && !m_cumulative)
                 return ProItem::ReturnFalse;
             if (args.count() != 1) {
-                logMessage(format("%1(variable) requires one argument.").arg(function));
+                logMessage(format("%1(variable) requires one argument.")
+                           .arg(function.toQString(m_tmp1)));
                 return ProItem::ReturnFalse;
             }
-            QHash<QString, QStringList> *hsh;
-            QHash<QString, QStringList>::Iterator it;
-            const QString &var = map(args.at(0));
+            QHash<ProString, ProStringList> *hsh;
+            QHash<ProString, ProStringList>::Iterator it;
+            const ProString &var = map(args.at(0));
             if (!(hsh = findValues(var, &it)))
                 return ProItem::ReturnFalse;
             if (hsh == &m_valuemapStack.top())
@@ -2814,12 +2875,13 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
             if (m_skipLevel && !m_cumulative)
                 return ProItem::ReturnFalse;
             if (args.count() != 1) {
-                logMessage(format("%1(variable) requires one argument.").arg(function));
+                logMessage(format("%1(variable) requires one argument.")
+                           .arg(function.toQString(m_tmp1)));
                 return ProItem::ReturnFalse;
             }
-            QHash<QString, QStringList> *hsh;
-            QHash<QString, QStringList>::Iterator it;
-            const QString &var = map(args.at(0));
+            QHash<ProString, ProStringList> *hsh;
+            QHash<ProString, ProStringList>::Iterator it;
+            const ProString &var = map(args.at(0));
             if (!(hsh = findValues(var, &it)))
                 return ProItem::ReturnFalse;
             if (m_valuemapStack.size() == 1)
@@ -2837,31 +2899,35 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
             // the third optional argument to include() controls warnings
             //      and is not used here
             if ((args.count() == 2) || (args.count() == 3) ) {
-                parseInto = args[1];
+                parseInto = args.at(1).toQString(m_tmp2);
             } else if (args.count() != 1) {
                 logMessage(format("include(file, into, silent) requires one, two or three arguments."));
                 return ProItem::ReturnFalse;
             }
-            QString fn = resolvePath(expandEnvVars(args.first()));
+            QString fn = resolvePath(expandEnvVars(args.at(0).toQString()));
             bool ok;
             if (parseInto.isEmpty()) {
                 ok = evaluateFile(fn);
             } else {
-                QHash<QString, QStringList> symbols;
+                QHash<ProString, ProStringList> symbols;
                 if ((ok = evaluateFileInto(fn, &symbols, 0))) {
-                    QHash<QString, QStringList> newMap;
-                    for (QHash<QString, QStringList>::ConstIterator
+                    QHash<ProString, ProStringList> newMap;
+                    for (QHash<ProString, ProStringList>::ConstIterator
                             it = m_valuemapStack.top().constBegin(),
                             end = m_valuemapStack.top().constEnd();
-                         it != end; ++it)
-                        if (!(it.key().startsWith(parseInto) &&
-                              (it.key().length() == parseInto.length()
-                               || it.key().at(parseInto.length()) == QLatin1Char('.'))))
+                            it != end; ++it) {
+                        const QString &ky = it.key().toQString(m_tmp1);
+                        if (!(ky.startsWith(parseInto) &&
+                              (ky.length() == parseInto.length()
+                               || ky.at(parseInto.length()) == QLatin1Char('.'))))
                             newMap[it.key()] = it.value();
-                    for (QHash<QString, QStringList>::ConstIterator it = symbols.constBegin();
-                         it != symbols.constEnd(); ++it)
-                        if (!it.key().startsWith(QLatin1Char('.')))
-                            newMap.insert(parseInto + QLatin1Char('.') + it.key(), it.value());
+                    }
+                    for (QHash<ProString, ProStringList>::ConstIterator it = symbols.constBegin();
+                         it != symbols.constEnd(); ++it) {
+                        const QString &ky = it.key().toQString(m_tmp1);
+                        if (!ky.startsWith(QLatin1Char('.')))
+                            newMap.insert(ProString(parseInto + QLatin1Char('.') + ky), it.value());
+                    }
                     m_valuemapStack.top() = newMap;
                 }
             }
@@ -2872,24 +2938,26 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 return ProItem::ReturnFalse;
             bool ignore_error = false;
             if (args.count() == 2) {
-                ignore_error = isTrue(args.at(1));
+                ignore_error = isTrue(args.at(1), m_tmp2);
             } else if (args.count() != 1) {
                 logMessage(format("load(feature) requires one or two arguments."));
                 return ProItem::ReturnFalse;
             }
             // XXX ignore_error unused
-            return returnBool(evaluateFeatureFile(expandEnvVars(args.first())));
+            return returnBool(evaluateFeatureFile(expandEnvVars(args.at(0).toQString())));
         }
         case T_DEBUG:
             // Yup - do nothing. Nothing is going to enable debug output anyway.
             return ProItem::ReturnFalse;
         case T_MESSAGE: {
             if (args.count() != 1) {
-                logMessage(format("%1(message) requires one argument.").arg(function));
+                logMessage(format("%1(message) requires one argument.")
+                           .arg(function.toQString(m_tmp1)));
                 return ProItem::ReturnFalse;
             }
-            QString msg = expandEnvVars(args.first());
-            fileMessage(QString::fromLatin1("Project %1: %2").arg(function.toUpper(), msg));
+            const QString &msg = expandEnvVars(args.at(0).toQString(m_tmp2));
+            fileMessage(QString::fromLatin1("Project %1: %2")
+                        .arg(function.toQString(m_tmp1).toUpper(), msg));
             // ### Consider real termination in non-cumulative mode
             return returnBool(function != QLatin1String("error"));
         }
@@ -2901,7 +2969,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
             }
             return returnBool(system((QLatin1String("cd ")
                                       + IoUtils::shellQuote(currentDirectory())
-                                      + QLatin1String(" && ") + args.first()).toLatin1().constData()) == 0);
+                                      + QLatin1String(" && ") + args.at(0)).toLatin1().constData()) == 0);
         }
 #endif
         case T_ISEMPTY: {
@@ -2909,11 +2977,11 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 logMessage(format("isEmpty(var) requires one argument."));
                 return ProItem::ReturnFalse;
             }
-            QStringList sl = values(map(args.first()));
+            const ProStringList &sl = values(map(args.at(0)));
             if (sl.count() == 0) {
                 return ProItem::ReturnTrue;
             } else if (sl.count() > 0) {
-                QString var = sl.first();
+                const ProString &var = sl.first();
                 if (var.isEmpty())
                     return ProItem::ReturnTrue;
             }
@@ -2924,7 +2992,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
                 logMessage(format("exists(file) requires one argument."));
                 return ProItem::ReturnFalse;
             }
-            QString file = resolvePath(expandEnvVars(args.first()));
+            const QString &file = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1)));
 
             if (IoUtils::exists(file)) {
                 return ProItem::ReturnTrue;
@@ -2940,19 +3008,20 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
             return ProItem::ReturnFalse;
         }
         case 0:
-            logMessage(format("'%1' is not a recognized test function").arg(function));
+            logMessage(format("'%1' is not a recognized test function")
+                       .arg(function.toQString(m_tmp1)));
             return ProItem::ReturnFalse;
         default:
-            logMessage(format("Function '%1' is not implemented").arg(function));
+            logMessage(format("Function '%1' is not implemented").arg(function.toQString(m_tmp1)));
             return ProItem::ReturnFalse;
     }
 }
 
-QHash<QString, QStringList> *ProFileEvaluator::Private::findValues(
-        const QString &variableName, QHash<QString, QStringList>::Iterator *rit)
+QHash<ProString, ProStringList> *ProFileEvaluator::Private::findValues(
+        const ProString &variableName, QHash<ProString, ProStringList>::Iterator *rit)
 {
     for (int i = m_valuemapStack.size(); --i >= 0; ) {
-        QHash<QString, QStringList>::Iterator it = m_valuemapStack[i].find(variableName);
+        QHash<ProString, ProStringList>::Iterator it = m_valuemapStack[i].find(variableName);
         if (it != m_valuemapStack[i].end()) {
             if (it->constBegin() == statics.fakeValue.constBegin())
                 return 0;
@@ -2963,15 +3032,15 @@ QHash<QString, QStringList> *ProFileEvaluator::Private::findValues(
     return 0;
 }
 
-QStringList &ProFileEvaluator::Private::valuesRef(const QString &variableName)
+ProStringList &ProFileEvaluator::Private::valuesRef(const ProString &variableName)
 {
-    QHash<QString, QStringList>::Iterator it = m_valuemapStack.top().find(variableName);
+    QHash<ProString, ProStringList>::Iterator it = m_valuemapStack.top().find(variableName);
     if (it != m_valuemapStack.top().end())
         return *it;
     for (int i = m_valuemapStack.size() - 1; --i >= 0; ) {
-        QHash<QString, QStringList>::ConstIterator it = m_valuemapStack.at(i).constFind(variableName);
+        QHash<ProString, ProStringList>::ConstIterator it = m_valuemapStack.at(i).constFind(variableName);
         if (it != m_valuemapStack.at(i).constEnd()) {
-            QStringList &ret = m_valuemapStack.top()[variableName];
+            ProStringList &ret = m_valuemapStack.top()[variableName];
             ret = *it;
             return ret;
         }
@@ -2979,22 +3048,22 @@ QStringList &ProFileEvaluator::Private::valuesRef(const QString &variableName)
     return m_valuemapStack.top()[variableName];
 }
 
-QStringList ProFileEvaluator::Private::valuesDirect(const QString &variableName) const
+ProStringList ProFileEvaluator::Private::valuesDirect(const ProString &variableName) const
 {
     for (int i = m_valuemapStack.size(); --i >= 0; ) {
-        QHash<QString, QStringList>::ConstIterator it = m_valuemapStack.at(i).constFind(variableName);
+        QHash<ProString, ProStringList>::ConstIterator it = m_valuemapStack.at(i).constFind(variableName);
         if (it != m_valuemapStack.at(i).constEnd()) {
             if (it->constBegin() == statics.fakeValue.constBegin())
                 break;
             return *it;
         }
     }
-    return QStringList();
+    return ProStringList();
 }
 
-QStringList ProFileEvaluator::Private::values(const QString &variableName) const
+ProStringList ProFileEvaluator::Private::values(const ProString &variableName) const
 {
-    QHash<QString, int>::ConstIterator vli = statics.varList.find(variableName);
+    QHash<ProString, int>::ConstIterator vli = statics.varList.find(variableName);
     if (vli != statics.varList.constEnd()) {
         int vlidx = *vli;
         QString ret;
@@ -3103,15 +3172,15 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName) const
             }
 #endif
         }
-        return QStringList(ret);
+        return ProStringList(ProString(ret, NoHash));
     }
 
-    QStringList result = valuesDirect(variableName);
+    ProStringList result = valuesDirect(variableName);
     if (result.isEmpty()) {
         if (variableName == statics.strTEMPLATE) {
-            result.append(QLatin1String("app"));
+            result.append(ProString("app", NoHash));
         } else if (variableName == statics.strQMAKE_DIR_SEP) {
-            result.append(m_option->dirlist_sep);
+            result.append(ProString(m_option->dirlist_sep, NoHash));
         }
     }
     return result;
@@ -3199,7 +3268,7 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName)
 }
 
 bool ProFileEvaluator::Private::evaluateFeatureFile(
-        const QString &fileName, QHash<QString, QStringList> *values, FunctionDefs *funcs)
+        const QString &fileName, QHash<ProString, ProStringList> *values, FunctionDefs *funcs)
 {
     QString fn = fileName;
     if (!fn.endsWith(QLatin1String(".prf")))
@@ -3228,10 +3297,11 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
 
       cool:
         // It's beyond me why qmake has this inside this if ...
-        QStringList &already = valuesRef(QLatin1String("QMAKE_INTERNAL_INCLUDED_FEATURES"));
-        if (already.contains(fn))
+        ProStringList &already = valuesRef(ProString("QMAKE_INTERNAL_INCLUDED_FEATURES"));
+        ProString afn(fn, NoHash);
+        if (already.contains(afn))
             return true;
-        already.append(fn);
+        already.append(afn);
     } else {
         fn = resolvePath(fn);
     }
@@ -3256,7 +3326,7 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
 }
 
 bool ProFileEvaluator::Private::evaluateFileInto(
-        const QString &fileName, QHash<QString, QStringList> *values, FunctionDefs *funcs)
+        const QString &fileName, QHash<ProString, ProStringList> *values, FunctionDefs *funcs)
 {
     ProFileEvaluator visitor(m_option);
     visitor.d->m_cumulative = false;
@@ -3327,18 +3397,26 @@ ProFileEvaluator::~ProFileEvaluator()
 
 bool ProFileEvaluator::contains(const QString &variableName) const
 {
-    return d->m_valuemapStack.top().contains(variableName);
+    return d->m_valuemapStack.top().contains(ProString(variableName));
+}
+
+static QStringList expandEnvVars(const ProStringList &x)
+{
+    QStringList ret;
+    foreach (const ProString &str, x)
+        ret << expandEnvVars(str.toQString());
+    return ret;
 }
 
 QStringList ProFileEvaluator::values(const QString &variableName) const
 {
-    return expandEnvVars(d->values(variableName));
+    return expandEnvVars(d->values(ProString(variableName)));
 }
 
 QStringList ProFileEvaluator::values(const QString &variableName, const ProFile *pro) const
 {
     // It makes no sense to put any kind of magic into expanding these
-    return expandEnvVars(d->m_filevaluemap.value(pro).value(variableName));
+    return expandEnvVars(d->m_filevaluemap.value(pro).value(ProString(variableName)));
 }
 
 QStringList ProFileEvaluator::absolutePathValues(
@@ -3400,9 +3478,9 @@ QStringList ProFileEvaluator::absoluteFileValues(
 
 ProFileEvaluator::TemplateType ProFileEvaluator::templateType()
 {
-    QStringList templ = values(statics.strTEMPLATE);
+    const ProStringList &templ = d->values(statics.strTEMPLATE);
     if (templ.count() >= 1) {
-        const QString &t = templ.last();
+        const QString &t = templ.last().toQString();
         if (!t.compare(QLatin1String("app"), Qt::CaseInsensitive))
             return TT_Application;
         if (!t.compare(QLatin1String("lib"), Qt::CaseInsensitive))
diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h
index 12935e9a245ebf279ee40e3d686875219fad4f55..7bc6fc9dd129c81fad446be2fceedf20c18a7c85 100644
--- a/src/shared/proparser/profileevaluator.h
+++ b/src/shared/proparser/profileevaluator.h
@@ -51,8 +51,8 @@ class ProFileEvaluator
 
 public:
     struct FunctionDefs {
-        QHash<QString, ProFunctionDef *> testFunctions;
-        QHash<QString, ProFunctionDef *> replaceFunctions;
+        QHash<ProString, ProFunctionDef *> testFunctions;
+        QHash<ProString, ProFunctionDef *> replaceFunctions;
     };
 
     enum TemplateType {
@@ -178,7 +178,7 @@ struct ProFileOption
   private:
     friend class ProFileEvaluator;
     friend class ProFileEvaluator::Private;
-    QHash<QString, QStringList> base_valuemap; // Cached results of qmake.conf, .qmake.cache & default_pre.prf
+    QHash<ProString, ProStringList> base_valuemap; // Cached results of qmake.conf, .qmake.cache & default_pre.prf
     ProFileEvaluator::FunctionDefs base_functions;
     QStringList feature_roots;
     QString qmakespec_name;
diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp
index 7f539df9ea6eb06b18a0a51de7acb144769895ce..6909c5c1c47d8af56dd96a2a1dcdcb51043bbdf6 100644
--- a/src/shared/proparser/proitems.cpp
+++ b/src/shared/proparser/proitems.cpp
@@ -30,9 +30,207 @@
 #include "proitems.h"
 
 #include <QtCore/QFileInfo>
+#include <QtCore/QSet>
 
 QT_BEGIN_NAMESPACE
 
+using namespace ProStringConstants;
+
+// from qhash.cpp
+static uint hash(const QChar *p, int n)
+{
+    uint h = 0;
+
+    while (n--) {
+        h = (h << 4) + (*p++).unicode();
+        h ^= (h & 0xf0000000) >> 23;
+        h &= 0x0fffffff;
+    }
+    return h;
+}
+
+ProString::ProString() :
+    m_offset(0), m_length(0), m_hash(0x80000000)
+{
+}
+
+ProString::ProString(const ProString &other) :
+        m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_hash(other.m_hash)
+{
+}
+
+ProString::ProString(const ProString &other, OmitPreHashing) :
+        m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_hash(0x80000000)
+{
+}
+
+ProString::ProString(const QString &str) :
+    m_string(str), m_offset(0), m_length(str.length())
+{
+    updatedHash();
+}
+
+ProString::ProString(const QString &str, OmitPreHashing) :
+    m_string(str), m_offset(0), m_length(str.length()), m_hash(0x80000000)
+{
+}
+
+ProString::ProString(const char *str) :
+    m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str))
+{
+    updatedHash();
+}
+
+ProString::ProString(const char *str, OmitPreHashing) :
+    m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_hash(0x80000000)
+{
+}
+
+uint ProString::updatedHash() const
+{
+     return (m_hash = hash(m_string.constData() + m_offset, m_length));
+}
+
+uint qHash(const ProString &str)
+{
+    if (!(str.m_hash & 0x80000000))
+        return str.m_hash;
+    return str.updatedHash();
+}
+
+QString ProString::toQString() const
+{
+    return m_string.mid(m_offset, m_length);
+}
+
+QString &ProString::toQString(QString &tmp) const
+{
+    return tmp.setRawData(m_string.constData() + m_offset, m_length);
+}
+
+bool ProString::operator==(const ProString &other) const
+{
+    if (m_length != other.m_length)
+        return false;
+    return !memcmp(m_string.constData() + m_offset,
+                   other.m_string.constData() + other.m_offset, m_length * 2);
+}
+
+bool ProString::operator==(const QString &other) const
+{
+    if (m_length != other.length())
+        return false;
+    return !memcmp(m_string.constData() + m_offset, other.constData(), m_length * 2);
+}
+
+bool ProString::operator==(const QLatin1String &other) const
+{
+    const ushort *uc = (ushort *)m_string.constData() + m_offset;
+    const ushort *e = uc + m_length;
+    const uchar *c = (uchar *)other.latin1();
+
+    if (!c)
+        return isEmpty();
+
+    while (*c) {
+        if (uc == e || *uc != *c)
+            return false;
+        ++uc;
+        ++c;
+    }
+    return (uc == e);
+}
+
+QString operator+(const ProString &one, const ProString &two)
+{
+    if (two.m_length) {
+        if (!one.m_length) {
+            return two.toQString();
+        } else {
+            QString neu(one.m_length + two.m_length, Qt::Uninitialized);
+            ushort *ptr = (ushort *)neu.constData();
+            memcpy(ptr, one.m_string.constData() + one.m_offset, one.m_length * 2);
+            memcpy(ptr + one.m_length, two.m_string.constData() + two.m_offset, two.m_length * 2);
+            return neu;
+        }
+    }
+    return one.toQString();
+}
+
+
+ProString ProString::mid(int off, int len) const
+{
+    ProString ret(*this, NoHash);
+    if (off > m_length)
+        off = m_length;
+    ret.m_offset += off;
+    ret.m_length -= off;
+    if (ret.m_length > len)
+        ret.m_length = len;
+    return ret;
+}
+
+ProString ProString::trimmed() const
+{
+    ProString ret(*this, NoHash);
+    int cur = m_offset;
+    int end = cur + m_length;
+    const QChar *data = m_string.constData();
+    for (; cur < end; cur++)
+        if (!data[cur].isSpace()) {
+            // No underrun check - we know there is at least one non-whitespace
+            while (data[end - 1].isSpace())
+                end--;
+            break;
+        }
+    ret.m_offset = cur;
+    ret.m_length = end - cur;
+    return ret;
+}
+
+QString ProStringList::join(const QString &sep) const
+{
+    int totalLength = 0;
+    const int sz = size();
+
+    for (int i = 0; i < sz; ++i)
+        totalLength += at(i).size();
+
+    if (sz)
+        totalLength += sep.size() * (sz - 1);
+
+    QString res(totalLength, Qt::Uninitialized);
+    QChar *ptr = (QChar *)res.constData();
+    for (int i = 0; i < sz; ++i) {
+        if (i) {
+            memcpy(ptr, sep.constData(), sep.size() * 2);
+            ptr += sep.size();
+        }
+        memcpy(ptr, at(i).constData(), at(i).size() * 2);
+        ptr += at(i).size();
+    }
+    return res;
+}
+
+void ProStringList::removeDuplicates()
+{
+    int n = size();
+    int j = 0;
+    QSet<ProString> seen;
+    seen.reserve(n);
+    for (int i = 0; i < n; ++i) {
+        const ProString &s = at(i);
+        if (seen.contains(s))
+            continue;
+        seen.insert(s);
+        if (j != i)
+            (*this)[j] = s;
+        ++j;
+    }
+    if (n != j)
+        erase(begin() + j, end());
+}
+
 void ProItem::disposeItems(ProItem *nitm)
 {
     for (ProItem *itm; (itm = nitm); ) {
diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h
index dfacf2dea1fa676ee1863d084d209d5c29ecf2e9..e8a43798885ff824eee8cc569eff57403373c9d8 100644
--- a/src/shared/proparser/proitems.h
+++ b/src/shared/proparser/proitems.h
@@ -31,7 +31,7 @@
 #define PROITEMS_H
 
 #include <QtCore/QString>
-#include <QtCore/QList>
+#include <QtCore/QVector>
 
 QT_BEGIN_NAMESPACE
 
@@ -49,6 +49,61 @@ private:
 };
 #endif
 
+namespace ProStringConstants {
+enum OmitPreHashing { NoHash };
+}
+
+class ProString {
+public:
+    ProString();
+    ProString(const ProString &other);
+    ProString(const ProString &other, ProStringConstants::OmitPreHashing);
+    explicit ProString(const QString &str);
+    ProString(const QString &str, ProStringConstants::OmitPreHashing);
+    explicit ProString(const char *str);
+    ProString(const char *str, ProStringConstants::OmitPreHashing);
+    QString toQString() const;
+    QString &toQString(QString &tmp) const;
+    bool operator==(const ProString &other) const;
+    bool operator==(const QString &other) const;
+    bool operator==(const QLatin1String &other) const;
+    bool operator!=(const ProString &other) const { return !(*this == other); }
+    bool operator!=(const QString &other) const { return !(*this == other); }
+    bool operator!=(const QLatin1String &other) const { return !(*this == other); }
+    bool isEmpty() const { return !m_length; }
+    int size() const { return m_length; }
+    const QChar *constData() const { return m_string.constData() + m_offset; }
+    ProString mid(int off, int len = -1) const;
+    ProString left(int len) const { return mid(0, len); }
+    ProString right(int len) const { return mid(qMax(0, size() - len)); }
+    ProString trimmed() const;
+    void clear() { m_string.clear(); m_length = 0; }
+
+private:
+    QString m_string;
+    int m_offset, m_length;
+    mutable uint m_hash;
+    uint updatedHash() const;
+    friend uint qHash(const ProString &str);
+    friend QString operator+(const ProString &one, const ProString &two);
+};
+Q_DECLARE_TYPEINFO(ProString, Q_MOVABLE_TYPE);
+
+uint qHash(const ProString &str);
+QString operator+(const ProString &one, const ProString &two);
+inline QString operator+(const ProString &one, const QString &two)
+    { return one + ProString(two, ProStringConstants::NoHash); }
+inline QString operator+(const QString &one, const ProString &two)
+    { return ProString(one, ProStringConstants::NoHash) + two; }
+
+class ProStringList : public QVector<ProString> {
+public:
+    ProStringList() {}
+    ProStringList(const ProString &str) { *this << str; }
+    QString join(const QString &sep) const;
+    void removeDuplicates();
+};
+
 class ProItem
 {
 public:
@@ -100,17 +155,18 @@ public:
         UniqueAddOperator   = 4
     };
 
-    ProVariable(const QString &name) : ProItem(VariableKind), m_variableKind(SetOperator), m_variable(name) {}
+    ProVariable(const ProString &name) : ProItem(VariableKind),
+            m_variableKind(SetOperator), m_variable(name) {}
     void setVariableOperator(VariableOperator variableKind) { m_variableKind = variableKind; }
     VariableOperator variableOperator() const { return m_variableKind; }
-    QString variable() const { return m_variable; }
-    void setValue(const QString &value) { m_value = value; }
-    QString value() const { return m_value; }
+    ProString variable() const { return m_variable; }
+    void setValue(const ProString &value) { m_value = value; }
+    ProString value() const { return m_value; }
 
 private:
     VariableOperator m_variableKind;
-    QString m_variable;
-    QString m_value;
+    ProString m_variable;
+    ProString m_value;
 };
 
 class ProCondition : public ProItem
@@ -143,17 +199,18 @@ class ProLoop : public ProItem
 {
 public:
     ProLoop(const QString &var, const QString &expr)
-        : ProItem(LoopKind), m_variable(var), m_expression(expr) {}
+        : ProItem(LoopKind), m_variable(ProString(var)),
+          m_expression(ProString(expr, ProStringConstants::NoHash)) {}
     ~ProLoop();
 
-    QString variable() const { return m_variable; }
-    QString expression() const { return m_expression; }
+    ProString variable() const { return m_variable; }
+    ProString expression() const { return m_expression; }
     ProItem *items() const { return m_proitems; }
     ProItem **itemsRef() { return &m_proitems; }
 
 private:
-    QString m_variable;
-    QString m_expression;
+    ProString m_variable;
+    ProString m_expression;
     ProItem *m_proitems;
 };
 
@@ -163,10 +220,10 @@ public:
     enum FunctionType { TestFunction, ReplaceFunction };
 
     ProFunctionDef(const QString &name, FunctionType type)
-        : ProItem(FunctionDefKind), m_name(name), m_type(type), m_refCount(1) {}
+        : ProItem(FunctionDefKind), m_name(ProString(name)), m_type(type), m_refCount(1) {}
     ~ProFunctionDef();
 
-    QString name() const { return m_name; }
+    ProString name() const { return m_name; }
     FunctionType type() const { return m_type; }
     ProItem *items() const { return m_proitems; }
     ProItem **itemsRef() { return &m_proitems; }
@@ -175,7 +232,7 @@ public:
     void deref() { if (!m_refCount.deref()) delete this; }
 
 private:
-    QString m_name;
+    ProString m_name;
     FunctionType m_type;
     ProItemRefCount m_refCount;
     ProItem *m_proitems;
diff --git a/src/shared/proparser/prowriter.cpp b/src/shared/proparser/prowriter.cpp
index d30dd5b0c91984c6e1ed55f44e8c80e96b9e8d16..c72f88bbe9f9e2b768f46e3d2e9663595990f5a6 100644
--- a/src/shared/proparser/prowriter.cpp
+++ b/src/shared/proparser/prowriter.cpp
@@ -43,7 +43,7 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines,
     for (ProItem *item = profile->items(); item; item = item->next()) {
         if (item->kind() == ProItem::VariableKind) {
             ProVariable *proVar = static_cast<ProVariable*>(item);
-            if (var == proVar->variable()
+            if (var == proVar->variable().toQString()
                 && proVar->variableOperator() != ProVariable::RemoveOperator
                 && proVar->variableOperator() != ProVariable::ReplaceOperator) {
 
@@ -93,7 +93,7 @@ static void findProVariables(ProItem *item, const QStringList &vars,
             findProVariables(static_cast<ProBranch*>(item)->elseItems(), vars, proVars);
         } else if (item->kind() == ProItem::VariableKind) {
             ProVariable *proVar = static_cast<ProVariable*>(item);
-            if (vars.contains(proVar->variable()))
+            if (vars.contains(proVar->variable().toQString()))
                 *proVars << proVar;
         }
     }