Some lexer improvement, mostly by avoiding QChar::isWhatever()
authorMartin Jones <martin.jones@nokia.com>
Thu, 21 Jul 2011 09:05:45 +0000 (19:05 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 30 Aug 2011 11:18:28 +0000 (13:18 +0200)
Change-Id: I330a45a2f611a594d9b0e9bb24ebef028654a8d8
Reviewed-on: http://codereview.qt.nokia.com/3756
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
src/declarative/qml/ftw/ftw.pri
src/declarative/qml/ftw/qdeclarativeutils_p.h [new file with mode: 0644]
src/declarative/qml/parser/qdeclarativejslexer.cpp
src/declarative/qml/qdeclarativecompiler.cpp
src/declarative/qml/qdeclarativedirparser.cpp
src/declarative/qml/v4/qdeclarativev4irbuilder.cpp

index 000c81b..190296a 100644 (file)
@@ -9,6 +9,7 @@ HEADERS +=  \
     $$PWD/qdeclarativerefcount_p.h \
     $$PWD/qdeclarativepool_p.h \
     $$PWD/qfieldlist_p.h \
+    $$PWD/qdeclarativeutils_p.h
 
 SOURCES += \
     $$PWD/qintrusivelist.cpp \
@@ -16,4 +17,3 @@ SOURCES += \
     $$PWD/qhashedstring.cpp \
     $$PWD/qdeclarativerefcount.cpp \
     $$PWD/qdeclarativepool.cpp \
-
diff --git a/src/declarative/qml/ftw/qdeclarativeutils_p.h b/src/declarative/qml/ftw/qdeclarativeutils_p.h
new file mode 100644 (file)
index 0000000..63e9001
--- /dev/null
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEUTIL_P_H
+#define QDECLARATIVEUTIL_P_H
+
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+namespace QDeclarativeUtils {
+
+inline bool isUpper(const QChar &qc)
+{
+    ushort c = qc.unicode();
+    return ((c >= 'A' && c <= 'Z') || (c > 127 && QChar::category(c) == QChar::Letter_Uppercase));
+}
+
+inline bool isLower(const QChar &qc)
+{
+    ushort c = qc.unicode();
+    return ((c >= 'a' && c <= 'z') || (c > 127 && QChar::category(c) == QChar::Letter_Lowercase));
+}
+
+inline bool isLetter(const QChar &qc)
+{
+    ushort c = qc.unicode();
+    return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c > 127 && qc.isLetter()));
+}
+
+inline bool isDigit(const QChar &qc)
+{
+    ushort c = qc.unicode();
+    return ((c >= '0' && c <= '9') || (c > 127 && qc.isDigit()));
+}
+
+inline bool isLetterOrNumber(const QChar &qc)
+{
+    ushort c = qc.unicode();
+    return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c > 127 && qc.isLetterOrNumber()));
+}
+
+inline bool isSpace(const QChar &qc)
+{
+    ushort c = qc.unicode();
+    return (c == 0x20 || (c >= 0x09 && c <= 0x0D) || c == 0x85 || (c > 127 && qc.isSpace()));
+}
+
+} // namespace QDeclarative
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEUTIL_P_H
index 980c15c..570548c 100644 (file)
@@ -42,7 +42,9 @@
 #include "qdeclarativejslexer_p.h"
 #include "qdeclarativejsengine_p.h"
 #include "qdeclarativejsnodepool_p.h"
+#include <private/qdeclarativeutils_p.h>
 #include <QtCore/QCoreApplication>
+#include <QtCore/QVarLengthArray>
 #include <QtCore/QDebug>
 
 QT_BEGIN_NAMESPACE
@@ -126,6 +128,7 @@ void Lexer::setCode(const QString &code, int lineno)
 
     _code = code;
     _tokenText.clear();
+    _tokenText.reserve(1024);
     _errorMessage.clear();
     _tokenSpell = QStringRef();
 
@@ -275,7 +278,7 @@ again:
     _validTokenText = false;
     _tokenLinePtr = _lastLinePtr;
 
-    while (_char.isSpace()) {
+    while (QDeclarativeUtils::isSpace(_char)) {
         if (_char == QLatin1Char('\n')) {
             _tokenLinePtr = _codePtr;
 
@@ -404,43 +407,44 @@ again:
         return T_DIVIDE_;
 
     case '.':
-        if (_char.isDigit()) {
-            QByteArray chars;
-            chars.reserve(32);
+        if (QDeclarativeUtils::isDigit(_char)) {
+            QVarLengthArray<char,32> chars;
 
-            chars += ch.unicode(); // append the `.'
+            chars.append(ch.unicode()); // append the `.'
 
-            while (_char.isDigit()) {
-                chars += _char.unicode();
+            while (QDeclarativeUtils::isDigit(_char)) {
+                chars.append(_char.unicode());
                 scanChar();
             }
 
-            if (_char.toLower() == QLatin1Char('e')) {
-                if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
-                                              _codePtr[1].isDigit())) {
+            if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) {
+                if (QDeclarativeUtils::isDigit(_codePtr[0]) || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
+                                              QDeclarativeUtils::isDigit(_codePtr[1]))) {
 
-                    chars += _char.unicode();
+                    chars.append(_char.unicode());
                     scanChar(); // consume `e'
 
                     if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) {
-                        chars += _char.unicode();
+                        chars.append(_char.unicode());
                         scanChar(); // consume the sign
                     }
 
-                    while (_char.isDigit()) {
-                        chars += _char.unicode();
+                    while (QDeclarativeUtils::isDigit(_char)) {
+                        chars.append(_char.unicode());
                         scanChar();
                     }
                 }
             }
 
+            chars.append('\0');
+
             const char *begin = chars.constData();
             const char *end = 0;
             bool ok = false;
 
             _tokenValue = qstrtod(begin, &end, &ok);
 
-            if (end != chars.end()) {
+            if (end - begin != chars.size() - 1) {
                 _errorCode = IllegalExponentIndicator;
                 _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Illegal syntax for exponential number");
                 return T_ERROR;
@@ -525,7 +529,7 @@ again:
     case '\'':
     case '"': {
         const QChar quote = ch;
-        _tokenText.clear();
+        _tokenText.resize(0);
         _validTokenText = true;
 
         bool multilineStringLiteral = false;
@@ -632,11 +636,11 @@ again:
     }
 
     default:
-        if (ch.isLetter() || ch == QLatin1Char('$') || ch == QLatin1Char('_') || (ch == QLatin1Char('\\') && _char == QLatin1Char('u'))) {
+        if (QDeclarativeUtils::isLetter(ch) || ch == QLatin1Char('$') || ch == QLatin1Char('_') || (ch == QLatin1Char('\\') && _char == QLatin1Char('u'))) {
             bool identifierWithEscapeChars = false;
             if (ch == QLatin1Char('\\')) {
                 identifierWithEscapeChars = true;
-                _tokenText.clear();
+                _tokenText.resize(0);
                 bool ok = false;
                 _tokenText += decodeUnicodeEscapeCharacter(&ok);
                 _validTokenText = true;
@@ -647,7 +651,7 @@ again:
                 }
             }
             while (true) {
-                if (_char.isLetterOrNumber() || _char == QLatin1Char('$') || _char == QLatin1Char('_')) {
+                if (QDeclarativeUtils::isLetterOrNumber(_char) || _char == QLatin1Char('$') || _char == QLatin1Char('_')) {
                     if (identifierWithEscapeChars)
                         _tokenText += _char;
 
@@ -655,7 +659,8 @@ again:
                 } else if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) {
                     if (! identifierWithEscapeChars) {
                         identifierWithEscapeChars = true;
-                        _tokenText = QString(_tokenStartPtr, _codePtr - _tokenStartPtr - 1);
+                        _tokenText.resize(0);
+                        _tokenText.insert(0, _tokenStartPtr, _codePtr - _tokenStartPtr - 1);
                         _validTokenText = true;
                     }
 
@@ -685,19 +690,18 @@ again:
                     return kind;
                 }
             }
-        } else if (ch.isDigit()) {
-            QByteArray chars;
-            chars.reserve(32);
-            chars += ch.unicode();
+        } else if (QDeclarativeUtils::isDigit(ch)) {
+            QVarLengthArray<char,32> chars;
+            chars.append(ch.unicode());
 
             if (ch == QLatin1Char('0') && (_char == 'x' || _char == 'X')) {
                 // parse hex integer literal
 
-                chars += _char.unicode();
+                chars.append(_char.unicode());
                 scanChar(); // consume `x'
 
                 while (isHexDigit(_char)) {
-                    chars += _char.unicode();
+                    chars.append(_char.unicode());
                     scanChar();
                 }
 
@@ -706,64 +710,66 @@ again:
             }
 
             // decimal integer literal
-            while (_char.isDigit()) {
-                chars += _char.unicode();
+            while (QDeclarativeUtils::isDigit(_char)) {
+                chars.append(_char.unicode());
                 scanChar(); // consume the digit
             }
 
             if (_char == QLatin1Char('.')) {
-                chars += _char.unicode();
+                chars.append(_char.unicode());
                 scanChar(); // consume `.'
 
-                while (_char.isDigit()) {
-                    chars += _char.unicode();
+                while (QDeclarativeUtils::isDigit(_char)) {
+                    chars.append(_char.unicode());
                     scanChar();
                 }
 
-                if (_char.toLower() == QLatin1Char('e')) {
-                    if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
-                                                  _codePtr[1].isDigit())) {
+                if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) {
+                    if (QDeclarativeUtils::isDigit(_codePtr[0]) || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
+                                                  QDeclarativeUtils::isDigit(_codePtr[1]))) {
 
-                        chars += _char.unicode();
+                        chars.append(_char.unicode());
                         scanChar(); // consume `e'
 
                         if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) {
-                            chars += _char.unicode();
+                            chars.append(_char.unicode());
                             scanChar(); // consume the sign
                         }
 
-                        while (_char.isDigit()) {
-                            chars += _char.unicode();
+                        while (QDeclarativeUtils::isDigit(_char)) {
+                            chars.append(_char.unicode());
                             scanChar();
                         }
                     }
                 }
-            } else if (_char.toLower() == QLatin1Char('e')) {
-                if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
-                                              _codePtr[1].isDigit())) {
+            } else if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) {
+                if (QDeclarativeUtils::isDigit(_codePtr[0]) || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
+                                              QDeclarativeUtils::isDigit(_codePtr[1]))) {
 
-                    chars += _char.unicode();
+                    chars.append(_char.unicode());
                     scanChar(); // consume `e'
 
                     if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) {
-                        chars += _char.unicode();
+                        chars.append(_char.unicode());
                         scanChar(); // consume the sign
                     }
 
-                    while (_char.isDigit()) {
-                        chars += _char.unicode();
+                    while (QDeclarativeUtils::isDigit(_char)) {
+                        chars.append(_char.unicode());
                         scanChar();
                     }
                 }
             }
 
+            chars.append('\0');
+
             const char *begin = chars.constData();
             const char *end = 0;
             bool ok = false;
 
             _tokenValue = qstrtod(begin, &end, &ok);
 
-            if (end != chars.end()) {
+            if (end - begin != chars.size() - 1) {
                 _errorCode = IllegalExponentIndicator;
                 _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Illegal syntax for exponential number");
                 return T_ERROR;
@@ -780,7 +786,7 @@ again:
 
 bool Lexer::scanRegExp(RegExpBodyPrefix prefix)
 {
-    _tokenText.clear();
+    _tokenText.resize(0);
     _validTokenText = true;
     _patternFlags = 0;
 
index c75570d..984e2c8 100644 (file)
@@ -64,6 +64,7 @@
 #include "private/qdeclarativescriptparser_p.h"
 #include "private/qdeclarativebinding_p.h"
 #include "private/qdeclarativev4compiler_p.h"
+#include "private/qdeclarativeutils_p.h"
 
 #include <QColor>
 #include <QDebug>
@@ -128,7 +129,7 @@ bool QDeclarativeCompiler::isAttachedPropertyName(const QString &name)
 
 bool QDeclarativeCompiler::isAttachedPropertyName(const QStringRef &name)
 {
-    return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z';
+    return !name.isEmpty() && QDeclarativeUtils::isUpper(name.at(0));
 }
 
 /*!
@@ -153,9 +154,9 @@ bool QDeclarativeCompiler::isSignalPropertyName(const QStringRef &name)
     if (!name.startsWith(on_string)) return false;
     int ns = name.size();
     for (int i = 2; i < ns; ++i) {
-        QChar curr = name.at(i);
-        if (curr == QLatin1Char('_')) continue;
-        if (curr >= QLatin1Char('A') && curr <= QLatin1Char('Z')) return true;
+        const QChar curr = name.at(i);
+        if (curr.unicode() == '_') continue;
+        if (QDeclarativeUtils::isUpper(curr)) return true;
         return false;
     }
     return false; // consists solely of underscores - invalid.
@@ -1418,7 +1419,7 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl
     // Note that the property name could start with any alpha or '_' or '$' character,
     // so we need to do the lower-casing of the first alpha character.
     for (int firstAlphaIndex = 0; firstAlphaIndex < name.size(); ++firstAlphaIndex) {
-        if (name.at(firstAlphaIndex) >= QLatin1Char('A') && name.at(firstAlphaIndex) <= QLatin1Char('Z')) {
+        if (QDeclarativeUtils::isUpper(name.at(firstAlphaIndex))) {
             name[firstAlphaIndex] = name.at(firstAlphaIndex).toLower();
             break;
         }
@@ -2274,7 +2275,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop
         COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name())));
 
     QString string = v->value.asString();
-    if (!string.at(0).isUpper())
+    if (!QDeclarativeUtils::isUpper(string.at(0)))
         return true;
 
     QStringList parts = string.split(QLatin1Char('.'));
@@ -2399,7 +2400,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
             COMPILE_EXCEPTION(&prop, tr("Duplicate property name"));
 
         QString propName = QString::fromUtf8(prop.name);
-        if (propName.at(0).isUpper())
+        if (QDeclarativeUtils::isUpper(propName.at(0)))
             COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter"));
 
         if (enginePrivate->v8engine()->illegalNames().contains(propName))
@@ -2408,29 +2409,43 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
         propNames.insert(prop.name);
     }
 
-    for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
-        const QDeclarativeParser::Object::DynamicSignal &currSig = obj->dynamicSignals.at(ii);
-        QByteArray name = currSig.name;
-        if (methodNames.contains(name))
-            COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name"));
-        QString nameStr = QString::fromUtf8(name);
-        if (nameStr.at(0).isUpper())
+    for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+        const QDeclarativeScript::Object::DynamicSignal &currSig = *s;
+
+        if (methodNames.testAndSet(currSig.name.hash())) {
+            for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2 != s;
+                 s2 = obj->dynamicSignals.next(s2)) {
+                if (s2->name == currSig.name)
+                    COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name"));
+            }
+        }
+
+        if (currSig.name.at(0).isUpper())
             COMPILE_EXCEPTION(&currSig, tr("Signal names cannot begin with an upper case letter"));
-        if (enginePrivate->v8engine()->illegalNames().contains(nameStr))
+        if (enginePrivate->v8engine()->illegalNames().contains(currSig.name))
             COMPILE_EXCEPTION(&currSig, tr("Illegal signal name"));
-        methodNames.insert(name);
     }
-    for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
-        const QDeclarativeParser::Object::DynamicSlot &currSlot = obj->dynamicSlots.at(ii);
-        QByteArray name = currSlot.name;
-        if (methodNames.contains(name))
-            COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
-        QString nameStr = QString::fromUtf8(name);
-        if (nameStr.at(0).isUpper())
+
+    for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+        const QDeclarativeScript::Object::DynamicSlot &currSlot = *s;
+
+        if (methodNames.testAndSet(currSlot.name.hash())) {
+            for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2;
+                 s2 = obj->dynamicSignals.next(s2)) {
+                if (s2->name == currSlot.name)
+                    COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
+            }
+            for (Object::DynamicSlot *s2 = obj->dynamicSlots.first(); s2 != s;
+                 s2 = obj->dynamicSlots.next(s2)) {
+                if (s2->name == currSlot.name)
+                    COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
+            }
+        }
+
+        if (currSlot.name.at(0).isUpper())
             COMPILE_EXCEPTION(&currSlot, tr("Method names cannot begin with an upper case letter"));
-        if (enginePrivate->v8engine()->illegalNames().contains(nameStr))
+        if (enginePrivate->v8engine()->illegalNames().contains(currSlot.name))
             COMPILE_EXCEPTION(&currSlot, tr("Illegal method name"));
-        methodNames.insert(name);
     }
 
     return true;
@@ -2485,7 +2500,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn
         int lastSlash = path.lastIndexOf(QLatin1Char('/'));
         if (lastSlash > -1) {
             QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
-            if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
+            if (!nameBase.isEmpty() && QDeclarativeUtils::isUpper(nameBase.at(0)))
                 newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(idx);
         }
     }
@@ -2704,18 +2719,18 @@ bool QDeclarativeCompiler::checkValidId(QDeclarativeParser::Value *v, const QStr
     if (val.isEmpty()) 
         COMPILE_EXCEPTION(v, tr( "Invalid empty ID"));
 
-    if (val.at(0).isLetter() && !val.at(0).isLower()) 
+    QChar ch = val.at(0);
+    if (QDeclarativeUtils::isLetter(ch) && !QDeclarativeUtils::isLower(ch))
         COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter"));
 
     QChar u(QLatin1Char('_'));
-    for (int ii = 0; ii < val.count(); ++ii) {
+    if (!QDeclarativeUtils::isLetter(ch) && ch != u)
+        COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
 
-        if (ii == 0 && !val.at(ii).isLetter() && val.at(ii) != u) {
-            COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
-        } else if (ii != 0 && !val.at(ii).isLetterOrNumber() && val.at(ii) != u)  {
+    for (int ii = 1; ii < val.count(); ++ii) {
+        ch = val.at(ii);
+        if (!QDeclarativeUtils::isLetterOrNumber(ch) && ch != u)
             COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores"));
-        }
-
     }
 
     if (enginePrivate->v8engine()->illegalNames().contains(val))
index 6798870..1008d39 100644 (file)
@@ -42,6 +42,7 @@
 #include "private/qdeclarativedirparser_p.h"
 #include "qdeclarativeerror.h"
 #include <private/qdeclarativeglobal_p.h>
+#include <private/qdeclarativeutils_p.h>
 
 #include <QtCore/QTextStream>
 #include <QtCore/QFile>
@@ -140,9 +141,9 @@ bool QDeclarativeDirParser::parse()
         while (index != length) {
             const QChar ch = line.at(index);
 
-            if (ch.isSpace()) {
+            if (QDeclarativeUtils::isSpace(ch)) {
                 do { ++index; }
-                while (index != length && line.at(index).isSpace());
+                while (index != length && QDeclarativeUtils::isSpace(line.at(index)));
 
             } else if (ch == QLatin1Char('#')) {
                 // recognized a comment
@@ -152,7 +153,7 @@ bool QDeclarativeDirParser::parse()
                 const int start = index;
 
                 do { ++index; }
-                while (index != length && !line.at(index).isSpace());
+                while (index != length && !QDeclarativeUtils::isSpace(line.at(index)));
 
                 const QString lexeme = line.mid(start, index - start);
 
index 9e66ff4..1b8abba 100644 (file)
@@ -44,6 +44,7 @@
 
 #include <private/qsganchors_p_p.h> // For AnchorLine
 #include <private/qdeclarativetypenamecache_p.h>
+#include <private/qdeclarativeutils_p.h>
 
 DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
 
@@ -587,7 +588,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast)
                 break;
 
             case IR::Name::AttachType:
-                if (name.at(0).isUpper()) {
+                if (QDeclarativeUtils::isUpper(name.at(0))) {
                     QByteArray utf8Name = name.toUtf8();
                     const char *enumName = utf8Name.constData();