summaryrefslogtreecommitdiffstats
path: root/src/tools/moc/generator.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-06-22 14:01:13 -0700
committerThiago Macieira <thiago.macieira@intel.com>2022-06-24 19:05:57 -0700
commit0978646a65f517f0026fbdd0639415d265876512 (patch)
treef1d8144cde4185c31438ec6a4b33de394fddcb07 /src/tools/moc/generator.cpp
parent3816b14ee8bc6f9722f3b76a32f968e334d0ed27 (diff)
moc: remove the attempt to create one large string literal
Commit dda9c9e2bc4fd2efe9e3fb0e451a8c3512f9a4d2 fixed some outstanding issues with moc's calculation of the maximum string length, but it missed one. This commit instead opts to remove the calculation entirely and instead have multiple char array members in the qt_meta_stringdata. We needed a single string back in Qt 4.0 when the stringdata *was* a single char array. Since 5.0, we've used a structure with multiple members and pointer arithmetic going past the end of the arrays, from the top of the object. That's UB, but since it's always been UB and can't be fixed until Qt 7 anyway, let's go full monty on it and have one char array per meta object string. The struct qt_meta_stringdata_Qt_t for namespace Qt now has 1217 stringdataXXX members. Pick-to: 6.2 6.3 6.4 Change-Id: I6d3880c7d99d4fc494c8fffd16fb0d1573e387dc Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/tools/moc/generator.cpp')
-rw-r--r--src/tools/moc/generator.cpp88
1 files changed, 30 insertions, 58 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 08003287cd..967178ec56 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -106,6 +106,27 @@ static inline uint lengthOfEscapedString(const QByteArray &str)
return str.length() - extra;
}
+// Prints \a s to \a out, breaking it into lines of at most ColumnWidth. The
+// opening and closing quotes are NOT included (it's up to the caller).
+static void printStringWithIndentation(FILE *out, const QByteArray &s)
+{
+ static constexpr int ColumnWidth = 72;
+ int len = s.length();
+ int idx = 0;
+
+ do {
+ int spanLen = qMin(ColumnWidth - 2, len - idx);
+ // don't cut escape sequences at the end of a line
+ int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
+ if (backSlashPos >= idx) {
+ int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
+ spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, len - idx);
+ }
+ fprintf(out, "\n \"%.*s\"", spanLen, s.constData() + idx);
+ idx += spanLen;
+ } while (idx < len);
+}
+
void Generator::strreg(const QByteArray &s)
{
if (!strings.contains(s))
@@ -231,23 +252,11 @@ void Generator::generateCode()
//
// Build stringdata struct
//
- const int constCharArraySizeLimit = 65535;
fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData());
fprintf(out, " uint offsetsAndSizes[%d];\n", int(strings.size() * 2));
- {
- int stringDataLength = 0;
- int stringDataCounter = 0;
- for (int i = 0; i < strings.size(); ++i) {
- int thisLength = lengthOfEscapedString(strings.at(i)) + 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);
-
+ for (int i = 0; i < strings.size(); ++i) {
+ int thisLength = lengthOfEscapedString(strings.at(i)) + 1;
+ fprintf(out, " char stringdata%d[%d];\n", i, thisLength);
}
fprintf(out, "};\n");
@@ -272,56 +281,19 @@ void Generator::generateCode()
idx += len + 1;
}
- fprintf(out, "\n },\n");
+ fprintf(out, "\n }");
}
//
-// Build stringdata array
+// Build stringdata arrays
//
- 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;
- } else if (len && s.at(0) >= '0' && s.at(0) <= '9') {
- fprintf(out, "\"\"");
- len += 2;
- }
- int idx = 0;
- while (idx < s.length()) {
- if (idx > 0) {
- col = 0;
- fprintf(out, "\"\n \"");
- }
- int spanLen = qMin(70, s.length() - idx);
- // don't cut escape sequences at the end of a line
- int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
- if (backSlashPos >= idx) {
- int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
- spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx);
- }
- fprintf(out, "%.*s", spanLen, s.constData() + idx);
- idx += spanLen;
- col += spanLen;
- }
- col += len + 2;
+ for (const QByteArray &s : qAsConst(strings)) {
+ fputc(',', out);
+ printStringWithIndentation(out, s);
}
// Terminate stringdata struct
- fprintf(out, "\"\n};\n");
+ fprintf(out, "\n};\n");
fprintf(out, "#undef QT_MOC_LITERAL\n\n");
//