Fix maximal literal string limitation in moc.
C++ standard advise to place 64k char limit for string literals, this patch improves moc output so it is not affected anymore. Task-number: QTBUG-36500 Change-Id: Iece630faaef45baebe8c7afe4fc51e0362c713de Reviewed-by: Olivier Goffart <ogoffart@woboq.com>bb10
parent
a2d7441b83
commit
ac79a25aae
|
|
@ -230,13 +230,23 @@ void Generator::generateCode()
|
|||
//
|
||||
// Build stringdata struct
|
||||
//
|
||||
const int constCharArraySizeLimit = 65535;
|
||||
fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData());
|
||||
fprintf(out, " QByteArrayData data[%d];\n", strings.size());
|
||||
{
|
||||
int len = 0;
|
||||
for (int i = 0; i < strings.size(); ++i)
|
||||
len += strings.at(i).length() + 1;
|
||||
fprintf(out, " char stringdata[%d];\n", len);
|
||||
int stringDataLength = 0;
|
||||
int stringDataCounter = 0;
|
||||
for (int i = 0; i < strings.size(); ++i) {
|
||||
int thisLength = strings.at(i).length() + 1;
|
||||
stringDataLength += thisLength;
|
||||
if (stringDataLength / constCharArraySizeLimit) {
|
||||
// save previous stringdata and start computing the next one.
|
||||
fprintf(out, " char stringdata%d[%d];\n", stringDataCounter++, stringDataLength - thisLength);
|
||||
stringDataLength = thisLength;
|
||||
}
|
||||
}
|
||||
fprintf(out, " char stringdata%d[%d];\n", stringDataCounter, stringDataLength);
|
||||
|
||||
}
|
||||
fprintf(out, "};\n");
|
||||
|
||||
|
|
@ -247,7 +257,7 @@ void Generator::generateCode()
|
|||
// QByteArrayData::data() implementation returning simply "this + offset".
|
||||
fprintf(out, "#define QT_MOC_LITERAL(idx, ofs, len) \\\n"
|
||||
" Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \\\n"
|
||||
" qptrdiff(offsetof(qt_meta_stringdata_%s_t, stringdata) + ofs \\\n"
|
||||
" qptrdiff(offsetof(qt_meta_stringdata_%s_t, stringdata0) + ofs \\\n"
|
||||
" - idx * sizeof(QByteArrayData)) \\\n"
|
||||
" )\n",
|
||||
qualifiedClassNameIdentifier.constData());
|
||||
|
|
@ -282,9 +292,18 @@ void Generator::generateCode()
|
|||
fprintf(out, " \"");
|
||||
int col = 0;
|
||||
int len = 0;
|
||||
int stringDataLength = 0;
|
||||
for (int i = 0; i < strings.size(); ++i) {
|
||||
QByteArray s = strings.at(i);
|
||||
len = s.length();
|
||||
stringDataLength += len + 1;
|
||||
if (stringDataLength >= constCharArraySizeLimit) {
|
||||
fprintf(out, "\",\n \"");
|
||||
stringDataLength = len + 1;
|
||||
col = 0;
|
||||
} else if (i)
|
||||
fputs("\\0", out); // add \0 at the end of each string
|
||||
|
||||
if (col && col + len >= 72) {
|
||||
fprintf(out, "\"\n \"");
|
||||
col = 0;
|
||||
|
|
@ -309,9 +328,6 @@ void Generator::generateCode()
|
|||
idx += spanLen;
|
||||
col += spanLen;
|
||||
}
|
||||
|
||||
if (i != strings.size() - 1) // skip the last \0 the c++ will add it for us
|
||||
fputs("\\0", out);
|
||||
col += len + 2;
|
||||
}
|
||||
|
||||
|
|
@ -546,7 +562,7 @@ void Generator::generateCode()
|
|||
//
|
||||
fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData());
|
||||
fprintf(out, " if (!_clname) return Q_NULLPTR;\n");
|
||||
fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata))\n"
|
||||
fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata0))\n"
|
||||
" return static_cast<void*>(const_cast< %s*>(this));\n",
|
||||
qualifiedClassNameIdentifier.constData(), cdef->classname.constData());
|
||||
for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one
|
||||
|
|
|
|||
|
|
@ -573,6 +573,7 @@ private slots:
|
|||
void relatedMetaObjectsNameConflict_data();
|
||||
void relatedMetaObjectsNameConflict();
|
||||
void strignLiteralsInMacroExtension();
|
||||
void veryLongStringData();
|
||||
|
||||
signals:
|
||||
void sigWithUnsignedArg(unsigned foo);
|
||||
|
|
@ -3309,6 +3310,75 @@ void tst_Moc::strignLiteralsInMacroExtension()
|
|||
QCOMPARE(mobj->classInfo(4).value(), "fooLiteral");
|
||||
}
|
||||
|
||||
class VeryLongStringData : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
#define repeat2(V) V V
|
||||
#define repeat4(V) repeat2(V) repeat2(V)
|
||||
#define repeat8(V) repeat4(V) repeat4(V)
|
||||
#define repeat16(V) repeat8(V) repeat8(V)
|
||||
#define repeat32(V) repeat16(V) repeat16(V)
|
||||
#define repeat64(V) repeat32(V) repeat32(V)
|
||||
#define repeat128(V) repeat64(V) repeat64(V)
|
||||
#define repeat256(V) repeat128(V) repeat128(V)
|
||||
#define repeat512(V) repeat256(V) repeat256(V)
|
||||
#define repeat1024(V) repeat512(V) repeat512(V)
|
||||
#define repeat2048(V) repeat1024(V) repeat1024(V)
|
||||
#define repeat4096(V) repeat2048(V) repeat2048(V)
|
||||
#define repeat8192(V) repeat4096(V) repeat4096(V)
|
||||
#define repeat16384(V) repeat8192(V) repeat8192(V)
|
||||
#define repeat32768(V) repeat16384(V) repeat16384(V)
|
||||
#define repeat65534(V) repeat32768(V) repeat16384(V) repeat8192(V) repeat4096(V) repeat2048(V) repeat1024(V) repeat512(V) repeat256(V) repeat128(V) repeat64(V) repeat32(V) repeat16(V) repeat8(V) repeat4(V) repeat2(V)
|
||||
|
||||
Q_CLASSINFO(repeat65534("n"), repeat65534("i"))
|
||||
Q_CLASSINFO(repeat65534("e"), repeat65534("r"))
|
||||
Q_CLASSINFO(repeat32768("o"), repeat32768("b"))
|
||||
Q_CLASSINFO(":", ")")
|
||||
|
||||
#undef repeat2
|
||||
#undef repeat4
|
||||
#undef repeat8
|
||||
#undef repeat16
|
||||
#undef repeat32
|
||||
#undef repeat64
|
||||
#undef repeat128
|
||||
#undef repeat256
|
||||
#undef repeat512
|
||||
#undef repeat1024
|
||||
#undef repeat2048
|
||||
#undef repeat4096
|
||||
#undef repeat8192
|
||||
#undef repeat16384
|
||||
#undef repeat32768
|
||||
#undef repeat65534
|
||||
};
|
||||
|
||||
void tst_Moc::veryLongStringData()
|
||||
{
|
||||
const QMetaObject *mobj = &VeryLongStringData::staticMetaObject;
|
||||
QCOMPARE(mobj->classInfoCount(), 4);
|
||||
|
||||
strlen(0);
|
||||
QCOMPARE(mobj->classInfo(0).name()[0], 'n');
|
||||
QCOMPARE(mobj->classInfo(0).value()[0], 'i');
|
||||
QCOMPARE(mobj->classInfo(1).name()[0], 'e');
|
||||
QCOMPARE(mobj->classInfo(1).value()[0], 'r');
|
||||
QCOMPARE(mobj->classInfo(2).name()[0], 'o');
|
||||
QCOMPARE(mobj->classInfo(2).value()[0], 'b');
|
||||
QCOMPARE(mobj->classInfo(3).name()[0], ':');
|
||||
QCOMPARE(mobj->classInfo(3).value()[0], ')');
|
||||
|
||||
QCOMPARE(strlen(mobj->classInfo(0).name()), static_cast<size_t>(65534));
|
||||
QCOMPARE(strlen(mobj->classInfo(0).value()), static_cast<size_t>(65534));
|
||||
QCOMPARE(strlen(mobj->classInfo(1).name()), static_cast<size_t>(65534));
|
||||
QCOMPARE(strlen(mobj->classInfo(1).value()), static_cast<size_t>(65534));
|
||||
QCOMPARE(strlen(mobj->classInfo(2).name()), static_cast<size_t>(32768));
|
||||
QCOMPARE(strlen(mobj->classInfo(2).value()), static_cast<size_t>(32768));
|
||||
QCOMPARE(strlen(mobj->classInfo(3).name()), static_cast<size_t>(1));
|
||||
QCOMPARE(strlen(mobj->classInfo(3).value()), static_cast<size_t>(1));
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_Moc)
|
||||
|
||||
// the generated code must compile with QT_NO_KEYWORDS
|
||||
|
|
|
|||
Loading…
Reference in New Issue