diff options
43 files changed, 595 insertions, 186 deletions
@@ -353,6 +353,7 @@ macSDKify() ;; esac + hasCFlags= echo "$1" | while read line; do case "$line" in QMAKE_CC=*|QMAKE_CXX=*|QMAKE_FIX_RPATH=*|QMAKE_AR=*|QMAKE_RANLIB=*|QMAKE_LINK=*|QMAKE_LINK_SHLIB=*) @@ -363,7 +364,11 @@ macSDKify() val=$(echo $sdk_val $(echo $val | cut -s -d ' ' -f 2-)) echo "$var=$val" ;; - QMAKE_CFLAGS=*|QMAKE_CXXFLAGS=*|QMAKE_LFLAGS=*) + QMAKE_CFLAGS=*) + echo "$line -isysroot $sysroot $version_min_flag" + hasCFlags="true"; + ;; + QMAKE_CXXFLAGS=*|QMAKE_LFLAGS=*) echo "$line -isysroot $sysroot $version_min_flag" ;; *) @@ -371,6 +376,10 @@ macSDKify() ;; esac done + + if [ -z "$hasCFlags" ]; then + echo "QMAKE_CFLAGS = -isysroot $sysroot $version_min_flag"; + fi } # relies on $QMAKESPEC being set correctly. parses include statements in @@ -844,6 +853,7 @@ fi setBootstrapVariable QMAKE_CC CC "$CC_TRANSFORM" setBootstrapVariable QMAKE_CXX CXX "$CC_TRANSFORM" setBootstrapVariable QMAKE_CXXFLAGS + setBootstrapVariable QMAKE_CFLAGS setBootstrapVariable QMAKE_CXXFLAGS_CXX1Z setBootstrapVariable QMAKE_CXXFLAGS_SPLIT_SECTIONS setBootstrapVariable QMAKE_LFLAGS @@ -874,6 +884,7 @@ fi echo "QT_MINOR_VERSION = $QT_MINOR_VERSION" >> "$mkfile" echo "QT_PATCH_VERSION = $QT_PATCH_VERSION" >> "$mkfile" echo "CONFIG_CXXFLAGS = $EXTRA_CXXFLAGS" >> "$mkfile" + echo "CONFIG_CFLAGS = \$(QMAKE_CFLAGS)" >> "$mkfile" echo "CONFIG_LFLAGS = $EXTRA_LFLAGS" >> "$mkfile" echo "RM_F = rm -f" >> "$mkfile" echo "RM_RF = rm -rf" >> "$mkfile" diff --git a/qmake/.prev_CMakeLists.txt b/qmake/.prev_CMakeLists.txt index e926f1d125..1e2bfb2448 100644 --- a/qmake/.prev_CMakeLists.txt +++ b/qmake/.prev_CMakeLists.txt @@ -6,6 +6,37 @@ qt_add_executable(qmake SOURCES + ../src/3rdparty/pcre2/src/config.h + ../src/3rdparty/pcre2/src/pcre2.h + ../src/3rdparty/pcre2/src/pcre2_auto_possess.c + ../src/3rdparty/pcre2/src/pcre2_chartables.c + ../src/3rdparty/pcre2/src/pcre2_compile.c + ../src/3rdparty/pcre2/src/pcre2_config.c + ../src/3rdparty/pcre2/src/pcre2_context.c + ../src/3rdparty/pcre2/src/pcre2_dfa_match.c + ../src/3rdparty/pcre2/src/pcre2_error.c + ../src/3rdparty/pcre2/src/pcre2_extuni.c + ../src/3rdparty/pcre2/src/pcre2_find_bracket.c + ../src/3rdparty/pcre2/src/pcre2_internal.h + ../src/3rdparty/pcre2/src/pcre2_intmodedep.h + ../src/3rdparty/pcre2/src/pcre2_jit_compile.c + ../src/3rdparty/pcre2/src/pcre2_maketables.c + ../src/3rdparty/pcre2/src/pcre2_match.c + ../src/3rdparty/pcre2/src/pcre2_match_data.c + ../src/3rdparty/pcre2/src/pcre2_newline.c + ../src/3rdparty/pcre2/src/pcre2_ord2utf.c + ../src/3rdparty/pcre2/src/pcre2_pattern_info.c + ../src/3rdparty/pcre2/src/pcre2_script_run.c + ../src/3rdparty/pcre2/src/pcre2_serialize.c + ../src/3rdparty/pcre2/src/pcre2_string_utils.c + ../src/3rdparty/pcre2/src/pcre2_study.c + ../src/3rdparty/pcre2/src/pcre2_substitute.c + ../src/3rdparty/pcre2/src/pcre2_substring.c + ../src/3rdparty/pcre2/src/pcre2_tables.c + ../src/3rdparty/pcre2/src/pcre2_ucd.c + ../src/3rdparty/pcre2/src/pcre2_ucp.h + ../src/3rdparty/pcre2/src/pcre2_valid_utf.c + ../src/3rdparty/pcre2/src/pcre2_xclass.c ../src/corelib/codecs/qutfcodec.cpp ../src/corelib/codecs/qutfcodec_p.h ../src/corelib/global/qglobal.cpp ../src/corelib/global/qglobal.h ../src/corelib/global/qlibraryinfo.cpp @@ -93,6 +124,7 @@ qt_add_executable(qmake qlocale.cpp-NOTFOUND qlocale.h-NOTFOUND qlocale_tools.cpp-NOTFOUND qlocale_tools_p.h-NOTFOUND qregexp.cpp-NOTFOUND qregexp.h-NOTFOUND + qregularexpression.cpp-NOTFOUND qregularexpression.h-NOTFOUND qromancalendar.cpp-NOTFOUND qromancalendar_p.h-NOTFOUND qstring.cpp-NOTFOUND qstring.h-NOTFOUND qstringlist.cpp-NOTFOUND qstringlist.h-NOTFOUND @@ -100,6 +132,7 @@ qt_add_executable(qmake qvsnprintf.cpp-NOTFOUND DEFINES (QT_VERSION_STR=\"\") + HAVE_CONFIG_H PROEVALUATOR_FULL QT_BOOTSTRAPPED QT_BUILD_QMAKE @@ -107,6 +140,8 @@ qt_add_executable(qmake QT_VERSION_MAJOR= QT_VERSION_MINOR= QT_VERSION_PATCH= + PUBLIC_DEFINES + PCRE2_CODE_UNIT_WIDTH=16 INCLUDE_DIRECTORIES (..)/include (..)/include/QtCore (..)/include/QtCore @@ -119,6 +154,8 @@ qt_add_executable(qmake generators/unix generators/win32 library + PUBLIC_INCLUDE_DIRECTORIES + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src/3rdparty/pcre2/src> PUBLIC_LIBRARIES Qt::Gui PRECOMPILED_HEADER @@ -146,6 +183,8 @@ qt_extend_target(qmake CONDITION WIN32 _CRT_SECURE_NO_WARNINGS _ENABLE_EXTENDED_ALIGNED_STORAGE _SCL_SECURE_NO_WARNINGS + PUBLIC_DEFINES + PCRE2_STATIC PUBLIC_LIBRARIES advapi32 kernel32 diff --git a/qmake/CMakeLists.txt b/qmake/CMakeLists.txt index 3bfd27f293..d724b44d59 100644 --- a/qmake/CMakeLists.txt +++ b/qmake/CMakeLists.txt @@ -9,6 +9,37 @@ qt_add_tool(qmake # special case TOOLS_TARGET Core # special case # GUI # special case: remove this SOURCES + ../src/3rdparty/pcre2/src/config.h + ../src/3rdparty/pcre2/src/pcre2.h + ../src/3rdparty/pcre2/src/pcre2_auto_possess.c + ../src/3rdparty/pcre2/src/pcre2_chartables.c + ../src/3rdparty/pcre2/src/pcre2_compile.c + ../src/3rdparty/pcre2/src/pcre2_config.c + ../src/3rdparty/pcre2/src/pcre2_context.c + ../src/3rdparty/pcre2/src/pcre2_dfa_match.c + ../src/3rdparty/pcre2/src/pcre2_error.c + ../src/3rdparty/pcre2/src/pcre2_extuni.c + ../src/3rdparty/pcre2/src/pcre2_find_bracket.c + ../src/3rdparty/pcre2/src/pcre2_internal.h + ../src/3rdparty/pcre2/src/pcre2_intmodedep.h + ../src/3rdparty/pcre2/src/pcre2_jit_compile.c + ../src/3rdparty/pcre2/src/pcre2_maketables.c + ../src/3rdparty/pcre2/src/pcre2_match.c + ../src/3rdparty/pcre2/src/pcre2_match_data.c + ../src/3rdparty/pcre2/src/pcre2_newline.c + ../src/3rdparty/pcre2/src/pcre2_ord2utf.c + ../src/3rdparty/pcre2/src/pcre2_pattern_info.c + ../src/3rdparty/pcre2/src/pcre2_script_run.c + ../src/3rdparty/pcre2/src/pcre2_serialize.c + ../src/3rdparty/pcre2/src/pcre2_string_utils.c + ../src/3rdparty/pcre2/src/pcre2_study.c + ../src/3rdparty/pcre2/src/pcre2_substitute.c + ../src/3rdparty/pcre2/src/pcre2_substring.c + ../src/3rdparty/pcre2/src/pcre2_tables.c + ../src/3rdparty/pcre2/src/pcre2_ucd.c + ../src/3rdparty/pcre2/src/pcre2_ucp.h + ../src/3rdparty/pcre2/src/pcre2_valid_utf.c + ../src/3rdparty/pcre2/src/pcre2_xclass.c ../src/corelib/codecs/qutfcodec.cpp ../src/corelib/codecs/qutfcodec_p.h ../src/corelib/global/qendian.cpp # special case ../src/corelib/global/qglobal.cpp ../src/corelib/global/qglobal.h @@ -70,8 +101,10 @@ qt_add_tool(qmake # special case ../src/corelib/text/qlocale_tools.cpp ../src/corelib/text/qlocale_tools_p.h ../src/corelib/tools/qmap.cpp ../src/corelib/tools/qmap.h ../src/corelib/text/qregexp.cpp ../src/corelib/text/qregexp.h + ../src/corelib/text/qregularexpression.cpp ../src/corelib/text/qregularexpression.h ../src/corelib/tools/qringbuffer.cpp # special case ../src/corelib/text/qstring.cpp ../src/corelib/text/qstring.h + ../src/corelib/text/qstringbuilder.cpp ../src/corelib/text/qstringbuilder.h ../src/corelib/text/qstringlist.cpp ../src/corelib/text/qstringlist.h ../src/corelib/text/qstringmatcher.h ../src/corelib/tools/qvector.h @@ -110,11 +143,15 @@ qt_add_tool(qmake # special case PROEVALUATOR_FULL QT_BOOTSTRAPPED QT_BUILD_QMAKE + QT_USE_QSTRINGBUILDER QT_NO_FOREACH QT_VERSION_STR="${PROJECT_VERSION}" # special case QT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} # special case QT_VERSION_MINOR=${PROJECT_VERSION_MINOR} # special case QT_VERSION_PATCH=${PROJECT_VERSION_PATCH} # special case + PCRE2_CODE_UNIT_WIDTH=16 + PCRE2_DISABLE_JIT + HAVE_CONFIG_H INCLUDE_DIRECTORIES # . # special case remove generators @@ -149,6 +186,8 @@ qt_extend_target(qmake CONDITION WIN32 _CRT_SECURE_NO_WARNINGS _ENABLE_EXTENDED_ALIGNED_STORAGE _SCL_SECURE_NO_WARNINGS + PUBLIC_DEFINES + PCRE2_STATIC PUBLIC_LIBRARIES advapi32 kernel32 diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 32c6d1dae6..1cdf9dee4b 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -31,10 +31,17 @@ QOBJS = \ qarraydata.o qbitarray.o qbytearray.o qbytearraylist.o qbytearraymatcher.o \ qcalendar.o qgregoriancalendar.o qromancalendar.o \ qcryptographichash.o qdatetime.o qhash.o \ - qlocale.o qlocale_tools.o qmap.o qregexp.o qringbuffer.o \ + qlocale.o qlocale_tools.o qmap.o qregularexpression.o qregexp.o qringbuffer.o \ qstringbuilder.o qstring.o qstringlist.o qversionnumber.o \ qvsnprintf.o qxmlstream.o qxmlutils.o \ - $(QTOBJS) $(QTOBJS2) + pcre2_auto_possess.o pcre2_chartables.o pcre2_compile.o pcre2_config.o \ + pcre2_context.o pcre2_dfa_match.o pcre2_error.o pcre2_extuni.o \ + pcre2_find_bracket.o pcre2_jit_compile.o pcre2_maketables.o pcre2_match.o \ + pcre2_match_data.o pcre2_newline.o pcre2_ord2utf.o pcre2_pattern_info.o pcre2_script_run.o \ + pcre2_serialize.o pcre2_string_utils.o pcre2_study.o pcre2_substitute.o \ + pcre2_substring.o pcre2_tables.o pcre2_ucd.o pcre2_valid_utf.o \ + pcre2_xclass.o \ + $(QTOBJS) $(QTOBJS2) # QTOBJS and QTOBJS2 are populated by Makefile.unix.* as for QTSRC (see below). # Note: qlibraryinfo.o omitted deliberately - see below. @@ -112,6 +119,7 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/text/qbytearraymatcher.cpp \ $(SOURCE_PATH)/src/corelib/text/qlocale.cpp \ $(SOURCE_PATH)/src/corelib/text/qlocale_tools.cpp \ + $(SOURCE_PATH)/src/corelib/text/qregularexpression.cpp \ $(SOURCE_PATH)/src/corelib/text/qregexp.cpp \ $(SOURCE_PATH)/src/corelib/text/qstringbuilder.cpp \ $(SOURCE_PATH)/src/corelib/text/qstring.cpp \ @@ -128,6 +136,32 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \ $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \ $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_auto_possess.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_chartables.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_compile.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_config.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_context.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_dfa_match.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_error.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_extuni.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_find_bracket.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_jit_compile.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_maketables.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_match.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_match_data.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_newline.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_ord2utf.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_pattern_info.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_script_run.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_serialize.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_string_utils.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_study.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_substitute.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_substring.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_tables.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_ucd.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_valid_utf.c \ + $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_xclass.c \ $(QTSRCS) $(QTSRCS2) # QTSRCS and QTSRCS2 come from Makefile.unix.* (concatenated with this # by configure); QTSRCS2 may include *.mm entries on macOS. @@ -136,6 +170,7 @@ DEPEND_SRC = \ CPPFLAGS = -g $(EXTRA_CPPFLAGS) \ -I$(QMKSRC) -I$(QMKLIBSRC) -I$(QMKGENSRC) \ -I$(SOURCE_PATH)/src/3rdparty/tinycbor/src \ + -I$(SOURCE_PATH)/src/3rdparty/pcre2/src \ -I$(QMKGENSRC)/unix -I$(QMKGENSRC)/win32 -I$(QMKGENSRC)/mac \ -I$(INC_PATH) -I$(INC_PATH)/QtCore \ -I$(INC_PATH)/QtCore/$(QT_VERSION) -I$(INC_PATH)/QtCore/$(QT_VERSION)/QtCore \ @@ -143,9 +178,12 @@ CPPFLAGS = -g $(EXTRA_CPPFLAGS) \ -I$(QMAKESPEC) \ -DQT_VERSION_STR=\"$(QT_VERSION)\" -DQT_VERSION_MAJOR=$(QT_MAJOR_VERSION) -DQT_VERSION_MINOR=$(QT_MINOR_VERSION) -DQT_VERSION_PATCH=$(QT_PATCH_VERSION) \ -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \ - -DQT_NO_FOREACH + -DQT_NO_FOREACH -DQT_USE_QSTRINGBUILDER \ + -DPCRE2_CODE_UNIT_WIDTH=16 -DHAVE_CONFIG_H\ + $(EXTRA_CPPFLAGS) CXXFLAGS = $(EXTRA_CXXFLAGS) $(CONFIG_CXXFLAGS) $(CPPFLAGS) +CFLAGS = $(CPPFLAGS) $(CONFIG_CFLAGS) LFLAGS = $(EXTRA_LFLAGS) $(CONFIG_LFLAGS) first all: $(BUILD_PATH)/bin/qmake$(EXEEXT) @@ -410,6 +448,9 @@ qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp qtemporaryfile.o: $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< +qregularexpression.o: $(SOURCE_PATH)/src/corelib/text/qregularexpression.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< + qregexp.o: $(SOURCE_PATH)/src/corelib/text/qregexp.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< @@ -494,4 +535,83 @@ qxmlutils.o: $(SOURCE_PATH)/src/corelib/serialization/qxmlutils.cpp qtextstream.o: $(SOURCE_PATH)/src/corelib/serialization/qtextstream.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< +pcre2_auto_possess.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_auto_possess.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_chartables.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_chartables.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_compile.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_compile.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_config.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_config.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_context.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_context.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_dfa_match.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_dfa_match.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_error.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_error.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_extuni.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_extuni.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_find_bracket.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_find_bracket.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_jit_compile.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_jit_compile.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_maketables.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_maketables.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_match.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_match.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_match_data.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_match_data.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_newline.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_newline.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_ord2utf.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_ord2utf.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_pattern_info.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_pattern_info.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_script_run.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_script_run.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_serialize.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_serialize.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_string_utils.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_string_utils.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_study.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_study.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_substitute.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_substitute.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_substring.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_substring.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_tables.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_tables.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_ucd.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_ucd.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_valid_utf.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_valid_utf.c + $(CC) -c -o $@ $(CFLAGS) $< + +pcre2_xclass.o: $(SOURCE_PATH)/src/3rdparty/pcre2/src/pcre2_xclass.c + $(CC) -c -o $@ $(CFLAGS) $< + + # DO NOT DELETE THIS LINE -- make depend depends on it diff --git a/qmake/Makefile.unix.mingw b/qmake/Makefile.unix.mingw index 6480171c69..816e5d67de 100644 --- a/qmake/Makefile.unix.mingw +++ b/qmake/Makefile.unix.mingw @@ -25,3 +25,6 @@ else RM_F = del /f RM_RF = rmdir /s /q endif +ifeq ($(CXX), g++) + CC = gcc +endif diff --git a/qmake/Makefile.unix.win32 b/qmake/Makefile.unix.win32 index faf09ac11e..3d38cd1b17 100644 --- a/qmake/Makefile.unix.win32 +++ b/qmake/Makefile.unix.win32 @@ -1,5 +1,5 @@ EXEEXT = .exe -EXTRA_CXXFLAGS = -DUNICODE -DMINGW_HAS_SECURE_API=1 +EXTRA_CPPFLAGS = -DPCRE2_STATIC -DUNICODE -DMINGW_HAS_SECURE_API=1 EXTRA_LFLAGS = -static -s -lole32 -luuid -ladvapi32 -lkernel32 -lnetapi32 QTOBJS = \ qfilesystemengine_win.o \ diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index 20644595d2..52a7a607e6 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -32,17 +32,20 @@ CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \ $(CFLAGS_EXTRA) \ -I$(QMKSRC) -I$(QMKSRC)\library -I$(QMKSRC)\generators -I$(QMKSRC)\generators\unix -I$(QMKSRC)\generators\win32 -I$(QMKSRC)\generators\mac \ -I$(SOURCE_PATH)/src/3rdparty/tinycbor/src \ + -I$(SOURCE_PATH)/src/3rdparty/pcre2/src \ -I$(INC_PATH) -I$(INC_PATH)\QtCore -I$(INC_PATH)\QtCore\$(QT_VERSION) -I$(INC_PATH)\QtCore\$(QT_VERSION)\QtCore \ -I$(BUILD_PATH)\src\corelib\global \ -I$(SOURCE_PATH)\mkspecs\$(QMAKESPEC) \ -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS \ -DQT_VERSION_STR=\"$(QT_VERSION)\" -DQT_VERSION_MAJOR=$(QT_MAJOR_VERSION) -DQT_VERSION_MINOR=$(QT_MINOR_VERSION) -DQT_VERSION_PATCH=$(QT_PATCH_VERSION) \ -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \ - -DQT_NO_FOREACH -DUNICODE -D_ENABLE_EXTENDED_ALIGNED_STORAGE -CFLAGS = $(CFLAGS_PCH) $(CFLAGS_BARE) $(CFLAGS) + -DQT_NO_FOREACH -DQT_USE_QSTRINGBUILDER -DUNICODE -D_ENABLE_EXTENDED_ALIGNED_STORAGE \ + -DPCRE2_CODE_UNIT_WIDTH=16 -DHAVE_CONFIG_H -DPCRE2_STATIC + +CFLAGS = $(CFLAGS_BARE) $(CFLAGS) CXXFLAGS_BARE = $(CFLAGS_BARE) -CXXFLAGS = $(CFLAGS) +CXXFLAGS = $(CFLAGS) $(CFLAGS_PCH) LFLAGS = LIBS = ole32.lib advapi32.lib shell32.lib netapi32.lib @@ -125,7 +128,34 @@ QTOBJS= \ qjsonparser.obj \ qjsonarray.obj \ qjsonobject.obj \ - qjsonvalue.obj + qjsonvalue.obj \ + qregularexpression.obj \ + pcre2_auto_possess.obj \ + pcre2_chartables.obj \ + pcre2_compile.obj \ + pcre2_config.obj \ + pcre2_context.obj \ + pcre2_dfa_match.obj \ + pcre2_error.obj \ + pcre2_extuni.obj \ + pcre2_find_bracket.obj \ + pcre2_jit_compile.obj \ + pcre2_maketables.obj \ + pcre2_match.obj \ + pcre2_match_data.obj \ + pcre2_newline.obj \ + pcre2_ord2utf.obj \ + pcre2_pattern_info.obj \ + pcre2_script_run.obj \ + pcre2_serialize.obj \ + pcre2_string_utils.obj \ + pcre2_study.obj \ + pcre2_substitute.obj \ + pcre2_substring.obj \ + pcre2_tables.obj \ + pcre2_ucd.obj \ + pcre2_valid_utf.obj \ + pcre2_xclass.obj \ first all: $(BUILD_PATH)\bin\qmake.exe binary: $(BUILD_PATH)\qmake\qmake.exe @@ -211,6 +241,9 @@ qmake_pch.obj: {$(SOURCE_PATH)\src\corelib\tools}.cpp{}.obj:: $(CXX) $(CXXFLAGS) $< +{$(SOURCE_PATH)\src\3rdparty\pcre2\src}.c{}.obj:: + $(CXX) $(CFLAGS) $< + # Make sure qlibraryinfo.obj isn't compiled with PCH enabled qlibraryinfo.obj: $(SOURCE_PATH)\src\corelib\global\qlibraryinfo.cpp $(CXX) $(CXXFLAGS_BARE) -DQT_BUILD_QMAKE_BOOTSTRAP $(SOURCE_PATH)\src\corelib\global\qlibraryinfo.cpp diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index c2f6df7787..c6aab40d85 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -30,7 +30,7 @@ #include "option.h" #include "meta.h" #include <qdir.h> -#include <qregexp.h> +#include <qregularexpression.h> #include <qcryptographichash.h> #include <qdebug.h> #include <qsettings.h> @@ -644,7 +644,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) bool isObj = project->values(ProKey(*it + ".CONFIG")).indexOf("no_link") == -1; if (!isObj) { for (int i = 0; i < sources.size(); ++i) { - if (sources.at(i).keyName() == inputs.at(input)) { + if (sources.at(i).keyName() == inputs.at(input).toQStringView()) { duplicate = true; break; } @@ -1865,11 +1865,12 @@ QString ProjectBuilderMakefileGenerator::fixForOutput(const QString &values) { //get the environment variables references - QRegExp reg_var("\\$\\((.*)\\)"); - for(int rep = 0; (rep = reg_var.indexIn(values, rep)) != -1;) { - if(project->values("QMAKE_PBX_VARS").indexOf(reg_var.cap(1)) == -1) - project->values("QMAKE_PBX_VARS").append(reg_var.cap(1)); - rep += reg_var.matchedLength(); + QRegularExpression reg_var("\\$\\((.*)\\)"); + QRegularExpressionMatch match; + for (int rep = 0; (match = reg_var.match(values, rep)).hasMatch();) { + if (project->values("QMAKE_PBX_VARS").indexOf(match.captured(1)) == -1) + project->values("QMAKE_PBX_VARS").append(match.captured(1)); + rep = match.capturedEnd(); } return values; @@ -2019,7 +2020,7 @@ ProjectBuilderMakefileGenerator::writeSettings(const QString &var, const ProStri for(int i = 0; i < indent_level; ++i) newline += "\t"; - static QRegExp allowedVariableCharacters("^[a-zA-Z0-9_]*$"); + static QRegularExpression allowedVariableCharacters("^[a-zA-Z0-9_]*$"); ret += var.contains(allowedVariableCharacters) ? var : quotedStringLiteral(var); ret += " = "; diff --git a/qmake/generators/mac/pbuilder_pbx.h b/qmake/generators/mac/pbuilder_pbx.h index 1b90a3bbeb..9b85764caa 100644 --- a/qmake/generators/mac/pbuilder_pbx.h +++ b/qmake/generators/mac/pbuilder_pbx.h @@ -56,8 +56,6 @@ class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator enum { SettingsAsList=0x01, SettingsNoQuote=0x02 }; inline QString writeSettings(const QString &var, const char *val, int flags=0, int indent_level=0) { return writeSettings(var, ProString(val), flags, indent_level); } - inline QString writeSettings(const QString &var, const QString &val, int flags=0, int indent_level=0) - { return writeSettings(var, ProString(val), flags, indent_level); } inline QString writeSettings(const QString &var, const ProString &val, int flags=0, int indent_level=0) { return writeSettings(var, ProStringList(val), flags, indent_level); } QString writeSettings(const QString &var, const ProStringList &vals, int flags=0, int indent_level=0); diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 5c61a3c65c..3ccd53f0a2 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -36,7 +36,7 @@ #include <qdir.h> #include <qfile.h> #include <qtextstream.h> -#include <qregexp.h> +#include <qregularexpression.h> #include <qhash.h> #include <qdebug.h> #include <qbuffer.h> @@ -1575,11 +1575,12 @@ MakefileGenerator::replaceExtraCompilerVariables( //do the work QString ret = orig_var; - QRegExp reg_var("\\$\\{.*\\}"); - reg_var.setMinimal(true); - for(int rep = 0; (rep = reg_var.indexIn(ret, rep)) != -1; ) { + QRegularExpression reg_var("\\$\\{.*\\}", QRegularExpression::InvertedGreedinessOption); + QRegularExpressionMatch match; + for (int rep = 0; (match = reg_var.match(ret, rep)).hasMatch(); ) { + rep = match.capturedStart(); QStringList val; - const ProString var(ret.mid(rep + 2, reg_var.matchedLength() - 3)); + const ProString var(ret.mid(rep + 2, match.capturedLength() - 3)); bool filePath = false; if(val.isEmpty() && var.startsWith(QLatin1String("QMAKE_VAR_"))) { const ProKey varname = var.mid(10).toKey(); @@ -1675,10 +1676,10 @@ MakefileGenerator::replaceExtraCompilerVariables( } else { fullVal = val.join(' '); } - ret.replace(rep, reg_var.matchedLength(), fullVal); - rep += fullVal.length(); + ret.replace(match.capturedStart(), match.capturedLength(), fullVal); + rep = match.capturedStart(), fullVal.length(); } else { - rep += reg_var.matchedLength(); + rep = match.capturedEnd(); } } @@ -2018,7 +2019,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) const bool existingDepsOnly = config.contains("dep_existing_only"); QStringList tmp_dep = project->values(ProKey(*it + ".depends")).toQStringList(); if (config.indexOf("combine") != -1) { - if (tmp_out.contains(QRegExp("(^|[^$])\\$\\{QMAKE_(?!VAR_)"))) { + if (tmp_out.contains(QRegularExpression("(^|[^$])\\$\\{QMAKE_(?!VAR_)"))) { warn_msg(WarnLogic, "QMAKE_EXTRA_COMPILERS(%s) with combine has variable output.", (*it).toLatin1().constData()); continue; @@ -2167,9 +2168,10 @@ MakefileGenerator::writeExtraVariables(QTextStream &t) const ProValueMap &vars = project->variables(); const ProStringList &exports = project->values("QMAKE_EXTRA_VARIABLES"); for (ProStringList::ConstIterator exp_it = exports.begin(); exp_it != exports.end(); ++exp_it) { - QRegExp rx((*exp_it).toQString(), Qt::CaseInsensitive, QRegExp::Wildcard); + auto pattern = QRegularExpression::wildcardToRegularExpression((*exp_it).toQString()); + QRegularExpression rx(pattern, QRegularExpression::CaseInsensitiveOption); for (ProValueMap::ConstIterator it = vars.begin(); it != vars.end(); ++it) { - if (rx.exactMatch(it.key().toQString())) + if (rx.match(it.key().toQString()).hasMatch()) outlist << ("EXPORT_" + it.key() + " = " + it.value().join(' ')); } } @@ -2273,7 +2275,7 @@ QString MakefileGenerator::fullBuildArgs() //output QString ofile = fileFixify(Option::output.fileName()); - if(!ofile.isEmpty() && ofile != project->first("QMAKE_MAKEFILE")) + if (!ofile.isEmpty() && ofile != project->first("QMAKE_MAKEFILE").toQStringView()) ret += " -o " + escapeFilePath(ofile); //inputs @@ -2314,7 +2316,7 @@ MakefileGenerator::findSubDirsSubTargets() const ProString ofile = subdirs[subdir]; QString oname = ofile.toQString(); QString fixedSubdir = oname; - fixedSubdir.replace(QRegExp("[^a-zA-Z0-9_]"),"-"); + fixedSubdir.replace(QRegularExpression("[^a-zA-Z0-9_]"),"-"); SubTarget *st = new SubTarget; st->name = oname; @@ -2386,7 +2388,7 @@ MakefileGenerator::findSubDirsSubTargets() const if(subdirs[subDep] == depends.at(depend)) { QString subName = subdirs[subDep].toQString(); QString fixedSubDep = subName; - fixedSubDep.replace(QRegExp("[^a-zA-Z0-9_]"),"-"); + fixedSubDep.replace(QRegularExpression("[^a-zA-Z0-9_]"),"-"); const ProKey dtkey(fixedSubDep + ".target"); if (!project->isEmpty(dtkey)) { st->depends += project->first(dtkey); @@ -2400,7 +2402,7 @@ MakefileGenerator::findSubDirsSubTargets() const if (!project->isEmpty(dskey)) d = project->first(dskey).toQString(); } - st->depends += "sub-" + d.replace(QRegExp("[^a-zA-Z0-9_]"),"-"); + st->depends += "sub-" + d.replace(QRegularExpression("[^a-zA-Z0-9_]"),"-"); } found = true; break; @@ -2408,7 +2410,7 @@ MakefileGenerator::findSubDirsSubTargets() const } if(!found) { QString depend_str = depends.at(depend).toQString(); - st->depends += depend_str.replace(QRegExp("[^a-zA-Z0-9_]"),"-"); + st->depends += depend_str.replace(QRegularExpression("[^a-zA-Z0-9_]"),"-"); } } } @@ -2417,7 +2419,7 @@ MakefileGenerator::findSubDirsSubTargets() const st->target = project->first(tkey).toQString(); } else { st->target = "sub-" + file; - st->target.replace(QRegExp("[^a-zA-Z0-9_]"), "-"); + st->target.replace(QRegularExpression("[^a-zA-Z0-9_]"), "-"); } } } @@ -2515,7 +2517,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT if(!abs_source_path.isEmpty() && out_directory.startsWith(abs_source_path)) out_directory = Option::output_dir + out_directory.mid(abs_source_path.length()); - QString out_directory_cdin = out_directory.isEmpty() ? "\n\t" + QString out_directory_cdin = out_directory.isEmpty() ? QString("\n\t") : "\n\tcd " + escapeFilePath(out_directory) + " && "; QString makefilein = " -f " + escapeFilePath(subtarget->makefile); @@ -2696,7 +2698,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT if(!recurse.contains(subtarget->name)) continue; - QString out_directory_cdin = out_directory.isEmpty() ? "\n\t" + QString out_directory_cdin = out_directory.isEmpty() ? QString("\n\t") : "\n\tcd " + escapeFilePath(out_directory) + " && "; QString makefilein = " -f " + escapeFilePath(subtarget->makefile); @@ -2882,12 +2884,12 @@ MakefileGenerator::escapeDependencyPath(const QString &path) const #ifdef Q_OS_UNIX // When running on Unix, we need to escape colons (which may appear // anywhere in a path, and would be mis-parsed as dependency separators). - static const QRegExp criticalChars(QStringLiteral("([\t :#])")); + static const QRegularExpression criticalChars(QStringLiteral("([\t :#])")); #else // MinGW make has a hack for colons which denote drive letters, and no // other colons may appear in paths. And escaping colons actually breaks // the make from the Android SDK. - static const QRegExp criticalChars(QStringLiteral("([\t #])")); + static const QRegularExpression criticalChars(QStringLiteral("([\t #])")); #endif ret.replace(criticalChars, QStringLiteral("\\\\1")); ret.replace(QLatin1Char('='), QStringLiteral("$(EQ)")); @@ -3070,8 +3072,8 @@ MakefileGenerator::findFileForDep(const QMakeLocalFileName &dep, const QMakeLoca const ProStringList &nodeplist = project->values("SKIP_DEPENDS"); for (ProStringList::ConstIterator it = nodeplist.begin(); it != nodeplist.end(); ++it) { - QRegExp regx((*it).toQString()); - if(regx.indexIn(dep.local()) != -1) { + QRegularExpression regx((*it).toQString()); + if (regx.match(dep.local()).hasMatch()) { found = true; break; } diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index bae32883b4..b80b6e3e08 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -140,10 +140,16 @@ protected: //escape virtual QString escapeFilePath(const QString &path) const = 0; ProString escapeFilePath(const ProString &path) const; + template<typename A, typename B> + QString escapeFilePath(const QStringBuilder<A, B> &path) const + { return escapeFilePath(QString(path)); } QStringList escapeFilePaths(const QStringList &paths) const; ProStringList escapeFilePaths(const ProStringList &paths) const; virtual QString escapeDependencyPath(const QString &path) const; ProString escapeDependencyPath(const ProString &path) const; + template<typename A, typename B> + QString escapeDependencyPath(const QStringBuilder<A, B> &path) const + { return escapeDependencyPath(QString(path)); } QStringList escapeDependencyPaths(const QStringList &paths) const; ProStringList escapeDependencyPaths(const ProStringList &paths) const; diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index 613c97fb85..ac6793cbf3 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -32,7 +32,7 @@ #include <qdir.h> #include <qfile.h> #include <qfileinfo.h> -#include <qregexp.h> +#include <qregularexpression.h> QT_BEGIN_NAMESPACE @@ -245,7 +245,7 @@ ProjectGenerator::init() v["INCLUDEPATH"] += inc.real(); } } - if(no_qt_files && file_no_path.indexOf(QRegExp("^q[a-z_0-9].h$")) != -1) + if (no_qt_files && file_no_path.contains(QRegularExpression("^q[a-z_0-9].h$"))) no_qt_files = false; QString h_ext; for(int hit = 0; hit < Option::h_ext.size(); ++hit) { diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h index 28302b4f15..1f32e4341f 100644 --- a/qmake/generators/unix/unixmake.h +++ b/qmake/generators/unix/unixmake.h @@ -50,7 +50,7 @@ protected: bool findLibraries(bool linkPrl, bool mergeLflags) override; QString escapeFilePath(const QString &path) const override; - ProString escapeFilePath(const ProString &path) const { return MakefileGenerator::escapeFilePath(path); } + using MakefileGenerator::escapeFilePath; QStringList &findDependencies(const QString &) override; void init() override; diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 0412b52813..09af15130f 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -30,7 +30,7 @@ #include "unixmake.h" #include "option.h" #include "meta.h" -#include <qregexp.h> +#include <qregularexpression.h> #include <qbytearray.h> #include <qfile.h> #include <qdir.h> @@ -134,7 +134,7 @@ UnixMakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator:: if (!dist_directory.startsWith(Option::dir_sep)) dist_directory.prepend(Option::dir_sep); - QString out_directory_cdin = out_directory.isEmpty() ? "\n\t" + QString out_directory_cdin = out_directory.isEmpty() ? QString("\n\t") : "\n\tcd " + escapeFilePath(out_directory) + " && "; QString makefilein = " -e -f " + escapeFilePath(subtarget->makefile) + " distdir DISTDIR=$(DISTDIR)" + escapeFilePath(dist_directory); @@ -290,7 +290,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if (project->isActiveConfig("gcc_MD_depends")) { ProStringList objects = project->values("OBJECTS"); for (ProStringList::Iterator it = objects.begin(); it != objects.end(); ++it) { - QString d_file = (*it).toQString().replace(QRegExp(Option::obj_ext + "$"), ".d"); + QString d_file = (*it).toQString().replace(QRegularExpression(Option::obj_ext + "$"), ".d"); t << "-include " << escapeDependencyPath(d_file) << Qt::endl; project->values("QMAKE_DISTCLEAN") << d_file; } @@ -346,7 +346,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(!d_file.isEmpty()) { d_file = odir + ".deps/" + fileFixify(d_file, FileFixifyBackwards) + ".d"; QString d_file_d = escapeDependencyPath(d_file); - QStringList deps = findDependencies((*it).toQString()).filter(QRegExp( + QStringList deps = findDependencies((*it).toQString()).filter(QRegularExpression( "((^|/)" + Option::h_moc_mod + "|" + Option::cpp_moc_ext + "$)")); if(!deps.isEmpty()) t << d_file_d << ": " << finalizeDependencyPaths(deps).join(' ') << Qt::endl; @@ -507,7 +507,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(do_incremental) { ProString s_ext = project->first("QMAKE_EXTENSION_SHLIB"); QString incr_target = var("QMAKE_ORIG_TARGET").replace( - QRegExp("\\." + s_ext), "").replace(QRegExp("^lib"), "") + "_incremental"; + QRegularExpression("\\." + s_ext), "").replace(QRegularExpression("^lib"), "") + "_incremental"; if(incr_target.indexOf(Option::dir_sep) != -1) incr_target = incr_target.right(incr_target.length() - (incr_target.lastIndexOf(Option::dir_sep) + 1)); @@ -749,7 +749,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) (!isShallowBundle ? (isFramework ? ("Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/Resources/") - : "Contents/") + : QString("Contents/")) : QString()) + "Info.plist"; bundledFiles << info_plist_out; @@ -1533,8 +1533,10 @@ std::pair<bool, QString> UnixMakefileGenerator::writeObjectsPart(QTextStream &t, for (ProStringList::ConstIterator objit = objs.begin(); objit != objs.end(); ++objit) { bool increment = false; for (ProStringList::ConstIterator incrit = incrs.begin(); incrit != incrs.end(); ++incrit) { - if ((*objit).toQString().indexOf(QRegExp((*incrit).toQString(), Qt::CaseSensitive, - QRegExp::Wildcard)) != -1) { + auto pattern = + QRegularExpression::wildcardToRegularExpression((*incrit).toQString(), + QRegularExpression::UnanchoredWildcardConversion); + if ((*objit).toQString().contains(QRegularExpression(pattern))) { increment = true; incrs_out.append((*objit)); break; diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 096b041056..7a717a80a9 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -31,7 +31,7 @@ #include <proitems.h> -#include <qregexp.h> +#include <qregularexpression.h> #include <qdir.h> #include <stdlib.h> #include <time.h> @@ -209,7 +209,7 @@ void MingwMakefileGenerator::writeIncPart(QTextStream &t) const ProStringList &incs = project->values("INCLUDEPATH"); for (ProStringList::ConstIterator incit = incs.begin(); incit != incs.end(); ++incit) { QString inc = (*incit).toQString(); - inc.replace(QRegExp("\\\\$"), ""); + inc.replace(QRegularExpression("\\\\$"), ""); if (!isystem.isEmpty() && isSystemInclude(inc)) t << isystem << ' '; diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index 355260c974..82c0983272 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -34,7 +34,7 @@ #include <qscopedpointer.h> #include <qstringlist.h> #include <qfileinfo.h> -#include <qregexp.h> +#include <qregularexpression.h> QT_BEGIN_NAMESPACE @@ -834,12 +834,13 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool) QFile manifestFile(Option::output_dir + QLatin1Char('/') + manifest); if (manifestFile.open(QFile::ReadOnly)) { const QString contents = manifestFile.readAll(); - QRegExp regexp("[\\\\/a-zA-Z0-9_\\-\\!]*\\.(png|jpg|jpeg)"); + QRegularExpression regexp("[\\\\/a-zA-Z0-9_\\-\\!]*\\.(png|jpg|jpeg)"); int pos = 0; while (pos > -1) { - pos = regexp.indexIn(contents, pos); + QRegularExpressionMatch m; + pos = contents.indexOf(regexp, pos, &m); if (pos >= 0) { - const QString match = regexp.cap(0); + const QString match = m.captured(0); icons.insert(match); pos += match.length(); } diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 2fb24201bd..cf58ead2e9 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -29,7 +29,7 @@ #include "msvc_nmake.h" #include "option.h" -#include <qregexp.h> +#include <qregularexpression.h> #include <qdir.h> #include <qdiriterator.h> #include <qset.h> @@ -86,8 +86,8 @@ QString NmakeMakefileGenerator::defaultInstall(const QString &t) if (project->isActiveConfig("debug_info")) { if (t == "dlltarget" || project->values(ProKey(t + ".CONFIG")).indexOf("no_dll") == -1) { - const QFileInfo targetFileInfo = project->first("DESTDIR") + project->first("TARGET") - + project->first("TARGET_EXT"); + const QFileInfo targetFileInfo(project->first("DESTDIR") + project->first("TARGET") + + project->first("TARGET_EXT")); const QString pdb_target = targetFileInfo.completeBaseName() + ".pdb"; QString src_targ = (project->isEmpty("DESTDIR") ? QString("$(DESTDIR)") : project->first("DESTDIR")) + pdb_target; QString dst_targ = filePrefixRoot(root, fileFixify(targetdir + pdb_target, FileFixifyAbsolute)); @@ -245,8 +245,8 @@ void NmakeMakefileGenerator::init() project->values("PRECOMPILED_PCH_C") = ProStringList(precompPchC); } - const QFileInfo targetFileInfo = project->first("DESTDIR") + project->first("TARGET") - + project->first("TARGET_EXT"); + const QFileInfo targetFileInfo(project->first("DESTDIR") + project->first("TARGET") + + project->first("TARGET_EXT")); const ProString targetBase = targetFileInfo.path() + '/' + targetFileInfo.completeBaseName(); if (project->first("TEMPLATE") == "lib" && project->isActiveConfig("shared")) { project->values("QMAKE_CLEAN").append(targetBase + ".exp"); @@ -370,12 +370,12 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t) for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) t << '{' << escapeDependencyPath(sourceDir) << '}' << (*cppit) << '{' << escapeDependencyPath(objDir) << '}' << Option::obj_ext << "::\n\t" - << var("QMAKE_RUN_CXX_IMP_BATCH").replace(QRegExp("\\$@"), fileVar("OBJECTS_DIR")) + << var("QMAKE_RUN_CXX_IMP_BATCH").replace(QRegularExpression("\\$@"), fileVar("OBJECTS_DIR")) << "\n\t$<\n<<\n\n"; for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) t << '{' << escapeDependencyPath(sourceDir) << '}' << (*cit) << '{' << escapeDependencyPath(objDir) << '}' << Option::obj_ext << "::\n\t" - << var("QMAKE_RUN_CC_IMP_BATCH").replace(QRegExp("\\$@"), fileVar("OBJECTS_DIR")) + << var("QMAKE_RUN_CC_IMP_BATCH").replace(QRegularExpression("\\$@"), fileVar("OBJECTS_DIR")) << "\n\t$<\n<<\n\n"; } } else { @@ -434,7 +434,7 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t) } const QString resourceId = (templateName == "app") ? "1" : "2"; - const bool incrementalLinking = project->values("QMAKE_LFLAGS").toQStringList().filter(QRegExp("(/|-)INCREMENTAL:NO")).isEmpty(); + const bool incrementalLinking = project->values("QMAKE_LFLAGS").toQStringList().filter(QRegularExpression("(/|-)INCREMENTAL:NO")).isEmpty(); if (incrementalLinking && !linkerSupportsEmbedding) { // Link a resource that contains the manifest without modifying the exe/dll after linking. diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 3002ce889c..9e93fe51f3 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -34,7 +34,7 @@ #include <qscopedpointer.h> #include <qfileinfo.h> -#include <qregexp.h> +#include <qregularexpression.h> using namespace QMakeInternal; @@ -321,7 +321,7 @@ triState operator!(const triState &rhs) QStringList VCToolBase::fixCommandLine(const QString &input) { // The splitting regexp is a bit bizarre for backwards compat reasons (why else ...). - return input.split(QRegExp(QLatin1String("(\n\t|\r\\\\h|\r\n)\\s*"))); + return input.split(QRegularExpression(QLatin1String("(\n\t|\r\\\\h|\r\n)\\s*"))); } static QString vcCommandSeparator() diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 112ad1f739..57f02c13d0 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -33,7 +33,7 @@ #include <qtextstream.h> #include <qstring.h> #include <qhash.h> -#include <qregexp.h> +#include <qregularexpression.h> #include <qstringlist.h> #include <qdir.h> #include <stdlib.h> @@ -561,7 +561,7 @@ void Win32MakefileGenerator::writeIncPart(QTextStream &t) const ProStringList &incs = project->values("INCLUDEPATH"); for(int i = 0; i < incs.size(); ++i) { QString inc = incs.at(i).toQString(); - inc.replace(QRegExp("\\\\$"), ""); + inc.replace(QRegularExpression("\\\\$"), ""); if(!inc.isEmpty()) t << "-I" << escapeFilePath(inc) << ' '; } @@ -588,7 +588,7 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) t << "####### Output directory\n\n"; if(!project->values("OBJECTS_DIR").isEmpty()) - t << "OBJECTS_DIR = " << escapeFilePath(var("OBJECTS_DIR").remove(QRegExp("\\\\$"))) << Qt::endl; + t << "OBJECTS_DIR = " << escapeFilePath(var("OBJECTS_DIR").remove(QRegularExpression("\\\\$"))) << Qt::endl; else t << "OBJECTS_DIR = . \n"; t << Qt::endl; @@ -860,7 +860,7 @@ QString Win32MakefileGenerator::escapeDependencyPath(const QString &path) const { QString ret = path; if (!ret.isEmpty()) { - static const QRegExp criticalChars(QStringLiteral("([\t #])")); + static const QRegularExpression criticalChars(QStringLiteral("([\t #])")); if (ret.contains(criticalChars)) ret = "\"" + ret + "\""; debug_msg(2, "EscapeDependencyPath: %s -> %s", path.toLatin1().constData(), ret.toLatin1().constData()); diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index d2171274d8..fac0541779 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -30,7 +30,7 @@ #include <qdir.h> #include <qfile.h> -#include <qregexp.h> +#include <qregularexpression.h> #ifdef Q_OS_WIN # include <windows.h> @@ -178,9 +178,9 @@ QString IoUtils::shellQuoteWin(const QString &arg) // The process-level standard quoting allows escaping quotes with backslashes (note // that backslashes don't escape themselves, unless they are followed by a quote). // Consequently, quotes are escaped and their preceding backslashes are doubled. - ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\"")); + ret.replace(QRegularExpression(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\"")); // Trailing backslashes must be doubled as well, as they are followed by a quote. - ret.replace(QRegExp(QLatin1String("(\\\\+)$")), QLatin1String("\\1\\1")); + ret.replace(QRegularExpression(QLatin1String("(\\\\+)$")), QLatin1String("\\1\\1")); // However, the shell also interprets the command, and no backslash-escaping exists // there - a quote always toggles the quoting state, but is nonetheless passed down // to the called process verbatim. In the unquoted state, the circumflex escapes diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h index 333f9ed889..09c5504fdf 100644 --- a/qmake/library/proitems.h +++ b/qmake/library/proitems.h @@ -70,9 +70,16 @@ public: ProString(); ProString(const ProString &other); ProString &operator=(const ProString &) = default; - PROITEM_EXPLICIT ProString(const QString &str); + template<typename A, typename B> + ProString &operator=(const QStringBuilder<A, B> &str) + { return *this = QString(str); } + ProString(const QString &str); PROITEM_EXPLICIT ProString(const QStringRef &str); PROITEM_EXPLICIT ProString(const char *str); + template<typename A, typename B> + ProString(const QStringBuilder<A, B> &str) + : ProString(QString(str)) + {} ProString(const QString &str, int offset, int length); void setValue(const QString &str); void clear() { m_string.clear(); m_length = 0; } @@ -83,12 +90,16 @@ public: ProString &prepend(const ProString &other); ProString &append(const ProString &other, bool *pending = nullptr); ProString &append(const QString &other) { return append(ProString(other)); } + template<typename A, typename B> + ProString &append(const QStringBuilder<A, B> &other) { return append(QString(other)); } ProString &append(const QLatin1String other); ProString &append(const char *other) { return append(QLatin1String(other)); } ProString &append(QChar other); ProString &append(const ProStringList &other, bool *pending = nullptr, bool skipEmpty1st = false); ProString &operator+=(const ProString &other) { return append(other); } ProString &operator+=(const QString &other) { return append(other); } + template<typename A, typename B> + ProString &operator+=(const QStringBuilder<A, B> &other) { return append(QString(other)); } ProString &operator+=(const QLatin1String other) { return append(other); } ProString &operator+=(const char *other) { return append(other); } ProString &operator+=(QChar other) { return append(other); } @@ -123,9 +134,13 @@ public: bool startsWith(const QString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().startsWith(sub, cs); } bool startsWith(const char *sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().startsWith(QLatin1String(sub), cs); } bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().startsWith(c, cs); } + template<typename A, typename B> + bool startsWith(const QStringBuilder<A, B> &str) { return startsWith(QString(str)); } bool endsWith(const ProString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().endsWith(sub.toQStringRef(), cs); } bool endsWith(const QString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().endsWith(sub, cs); } bool endsWith(const char *sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().endsWith(QLatin1String(sub), cs); } + template<typename A, typename B> + bool endsWith(const QStringBuilder<A, B> &str) { return endsWith(QString(str)); } bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().endsWith(c, cs); } int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().indexOf(s, from, cs); } int indexOf(const char *s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().indexOf(QLatin1String(s), from, cs); } @@ -179,10 +194,15 @@ private: }; Q_DECLARE_TYPEINFO(ProString, Q_MOVABLE_TYPE); + class ProKey : public ProString { public: ALWAYS_INLINE ProKey() : ProString() {} explicit ProKey(const QString &str); + template<typename A, typename B> + ProKey(const QStringBuilder<A, B> &str) + : ProString(str) + {} PROITEM_EXPLICIT ProKey(const char *str); ProKey(const QString &str, int off, int len); ProKey(const QString &str, int off, int len, uint hash); @@ -206,31 +226,43 @@ private: }; Q_DECLARE_TYPEINFO(ProKey, Q_MOVABLE_TYPE); +template <> struct QConcatenable<ProString> : private QAbstractConcatenable +{ + typedef ProString type; + typedef QString ConvertTo; + enum { ExactSize = true }; + static int size(const ProString &a) { return a.length(); } + static inline void appendTo(const ProString &a, QChar *&out) + { + const auto n = a.size(); + memcpy(out, a.toQStringView().data(), sizeof(QChar) * n); + out += n; + } +}; + +template <> struct QConcatenable<ProKey> : private QAbstractConcatenable +{ + typedef ProKey type; + typedef QString ConvertTo; + enum { ExactSize = true }; + static int size(const ProKey &a) { return a.length(); } + static inline void appendTo(const ProKey &a, QChar *&out) + { + const auto n = a.size(); + memcpy(out, a.toQStringView().data(), sizeof(QChar) * n); + out += n; + } +}; + + size_t qHash(const ProString &str); -QString operator+(const ProString &one, const ProString &two); -inline QString operator+(const ProString &one, const QString &two) - { return one.toQStringRef() + two; } -inline QString operator+(const QString &one, const ProString &two) - { return one + two.toQStringRef(); } - -inline QString operator+(const ProString &one, const char *two) - { return one.toQStringRef() + QLatin1String(two); } -inline QString operator+(const char *one, const ProString &two) - { return QLatin1String(one) + two.toQStringRef(); } -inline QString operator+(const ProString &one, QChar two) - { return one.toQStringRef() + two; } -inline QString operator+(QChar one, const ProString &two) - { return one + two.toQStringRef(); } inline QString &operator+=(QString &that, const ProString &other) { return that += other.toQStringRef(); } -inline bool operator==(const QString &that, const ProString &other) - { return other == that; } -inline bool operator!=(const QString &that, const ProString &other) - { return !(other == that); } - QTextStream &operator<<(QTextStream &t, const ProString &str); +template<typename A, typename B> +QTextStream &operator<<(QTextStream &t, const QStringBuilder<A, B> &str) { return t << QString(str); } // This class manages read-only access to a ProString via a raw data QString // temporary, ensuring that the latter is accessed exclusively. @@ -296,6 +328,8 @@ public: QString join(const ProString &sep) const; QString join(const QString &sep) const; QString join(QChar sep) const; + template<typename A, typename B> + QString join(const QStringBuilder<A, B> &str) { return join(QString(str)); } void insertUnique(const ProStringList &value); diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 460720168f..96583e5e76 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -39,7 +39,7 @@ #include <qfile.h> #include <qfileinfo.h> #include <qlist.h> -#include <qregexp.h> +#include <qregularexpression.h> #include <qset.h> #include <qstringlist.h> #include <qtextstream.h> @@ -639,7 +639,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( if (!var.isEmpty()) { const auto strings = values(map(var)); if (regexp) { - QRegExp sepRx(sep); + QRegularExpression sepRx(sep, QRegularExpression::DotMatchesEverythingOption); + if (!sepRx.isValid()) { + evalError(fL1S("section(): Encountered invalid regular expression '%1'.").arg(sep)); + goto allfail; + } for (const ProString &str : strings) { ProStringRwUser u1(str, m_tmp[m_toggle ^= 1]); ret << u1.extract(u1.str().section(sepRx, beg, end)); @@ -890,11 +894,15 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( m_valuemapStack.top()[ret.at(0).toKey()] = lst; break; } case E_FIND: { - QRegExp regx(args.at(1).toQString()); + QRegularExpression regx(args.at(1).toQString(), QRegularExpression::DotMatchesEverythingOption); + if (!regx.isValid()) { + evalError(fL1S("find(): Encountered invalid regular expression '%1'.").arg(regx.pattern())); + goto allfail; + } const auto vals = values(map(args.at(0))); for (const ProString &val : vals) { ProStringRoUser u1(val, m_tmp[m_toggle ^= 1]); - if (regx.indexIn(u1.str()) != -1) + if (u1.str().contains(regx)) ret += val; } break; @@ -990,7 +998,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( case E_RE_ESCAPE: for (int i = 0; i < args.size(); ++i) { ProStringRwUser u1(args.at(i), m_tmp1); - ret << u1.extract(QRegExp::escape(u1.str())); + ret << u1.extract(QRegularExpression::escape(u1.str())); } break; case E_VAL_ESCAPE: { @@ -1038,8 +1046,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( dirs.append(QString()); } - r.detach(); // Keep m_tmp out of QRegExp's cache - QRegExp regex(r, Qt::CaseSensitive, QRegExp::Wildcard); + QString pattern = QRegularExpression::wildcardToRegularExpression(r); + QRegularExpression regex(pattern, QRegularExpression::DotMatchesEverythingOption); + if (!regex.isValid()) { + evalError(fL1S("section(): Encountered invalid wildcard expression '%1'.").arg(pattern)); + goto allfail; + } for (int d = 0; d < dirs.count(); d++) { QString dir = dirs[d]; QDir qdir(pfx + dir); @@ -1051,7 +1063,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( if (recursive) dirs.append(fname + QLatin1Char('/')); } - if (regex.exactMatch(qdir[i])) + if (regex.match(qdir[i]).hasMatch()) ret += ProString(fname).setSource(currentFileId()); } } @@ -1086,7 +1098,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( } #endif case E_REPLACE: { - const QRegExp before(args.at(1).toQString()); + const QRegularExpression before(args.at(1).toQString(), QRegularExpression::DotMatchesEverythingOption); + if (!before.isValid()) { + evalError(fL1S("replace(): Encountered invalid regular expression '%1'.").arg(before.pattern())); + goto allfail; + } ProStringRwUser u2(args.at(2), m_tmp2); const QString &after = u2.str(); const auto vals = values(map(args.at(0))); @@ -1528,21 +1544,24 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ok; if (args.count() == 2) return returnBool(vars.contains(map(args.at(1)))); - QRegExp regx; + QRegularExpression regx; + regx.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); ProStringRoUser u1(args.at(2), m_tmp1); const QString &qry = u1.str(); - if (qry != QRegExp::escape(qry)) { - QString copy = qry; - copy.detach(); - regx.setPattern(copy); + if (qry != QRegularExpression::escape(qry)) { + regx.setPattern(QRegularExpression::anchoredPattern(qry)); + if (!regx.isValid()) { + evalError(fL1S("infile(): Encountered invalid regular expression '%1'.").arg(qry)); + return ReturnFalse; + } } const auto strings = vars.value(map(args.at(1))); for (const ProString &s : strings) { if (s == qry) return ReturnTrue; - if (!regx.isEmpty()) { + if (!regx.pattern().isEmpty()) { ProStringRoUser u2(s, m_tmp[m_toggle ^= 1]); - if (regx.exactMatch(u2.str())) + if (regx.match(u2.str()).hasMatch()) return ReturnTrue; } } @@ -1590,11 +1609,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( case T_CONTAINS: { ProStringRoUser u1(args.at(1), m_tmp1); const QString &qry = u1.str(); - QRegExp regx; - if (qry != QRegExp::escape(qry)) { - QString copy = qry; - copy.detach(); - regx.setPattern(copy); + QRegularExpression regx; + regx.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); + if (qry != QRegularExpression::escape(qry)) { + regx.setPattern(QRegularExpression::anchoredPattern(qry)); + if (!regx.isValid()) { + evalError(fL1S("contains(): Encountered invalid regular expression '%1'.").arg(qry)); + return ReturnFalse; + } } const ProStringList &l = values(map(args.at(0))); if (args.count() == 2) { @@ -1602,9 +1624,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( const ProString &val = l[i]; if (val == qry) return ReturnTrue; - if (!regx.isEmpty()) { + if (!regx.pattern().isEmpty()) { ProStringRoUser u2(val, m_tmp[m_toggle ^= 1]); - if (regx.exactMatch(u2.str())) + if (regx.match(u2.str()).hasMatch()) return ReturnTrue; } } @@ -1617,9 +1639,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( if (val.toQStringRef() == mutuals[mut].trimmed()) { if (val == qry) return ReturnTrue; - if (!regx.isEmpty()) { + if (!regx.pattern().isEmpty()) { ProStringRoUser u2(val, m_tmp[m_toggle ^= 1]); - if (regx.exactMatch(u2.str())) + if (regx.match(u2.str()).hasMatch()) return ReturnTrue; } return ReturnFalse; diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index 7041a2402e..f78537c340 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -41,7 +41,7 @@ #include <qfile.h> #include <qfileinfo.h> #include <qlist.h> -#include <qregexp.h> +#include <qregularexpression.h> #include <qset.h> #include <qstack.h> #include <qstring.h> @@ -334,7 +334,7 @@ ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, int sourc } static void replaceInList(ProStringList *varlist, - const QRegExp ®exp, const QString &replace, bool global, QString &tmp) + const QRegularExpression ®exp, const QString &replace, bool global, QString &tmp) { for (ProStringList::Iterator varit = varlist->begin(); varit != varlist->end(); ) { ProStringRoUser u1(*varit, tmp); @@ -898,9 +898,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable( QString pattern = func[1].toString(); QString replace = func[2].toString(); if (quote) - pattern = QRegExp::escape(pattern); + pattern = QRegularExpression::escape(pattern); - QRegExp regexp(pattern, case_sense ? Qt::CaseSensitive : Qt::CaseInsensitive); + QRegularExpression regexp(pattern, case_sense ? QRegularExpression::NoPatternOption : + QRegularExpression::CaseInsensitiveOption); // 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. @@ -1635,17 +1636,17 @@ bool QMakeEvaluator::isActiveConfig(const QStringRef &config, bool regex) return m_hostBuild; if (regex && (config.contains(QLatin1Char('*')) || config.contains(QLatin1Char('?')))) { - QRegExp re(config.toString(), Qt::CaseSensitive, QRegExp::Wildcard); + QRegularExpression re(QRegularExpression::wildcardToRegularExpression(config.toString())); // mkspecs - if (re.exactMatch(m_qmakespecName)) + if (re.match(m_qmakespecName).hasMatch()) return true; // CONFIG variable const auto configValues = values(statics.strCONFIG); for (const ProString &configValue : configValues) { ProStringRoUser u1(configValue, m_tmp[m_toggle ^= 1]); - if (re.exactMatch(u1.str())) + if (re.match(u1.str()).hasMatch()) return true; } } else { diff --git a/qmake/main.cpp b/qmake/main.cpp index c0e6088d80..3cd79145e5 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -34,7 +34,7 @@ #include "metamakefile.h" #include <qnamespace.h> #include <qdebug.h> -#include <qregexp.h> +#include <qregularexpression.h> #include <qdir.h> #include <qdiriterator.h> #include <stdio.h> @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE #ifdef Q_OS_WIN struct SedSubst { - QRegExp from; + QRegularExpression from; QString to; }; Q_DECLARE_TYPEINFO(SedSubst, Q_MOVABLE_TYPE); @@ -85,7 +85,7 @@ static int doSed(int argc, char **argv) return 3; } QChar sep = ++j < cmd.length() ? cmd.at(j) : QChar(); - Qt::CaseSensitivity matchcase = Qt::CaseSensitive; + QRegularExpression::PatternOptions matchcase = QRegularExpression::NoPatternOption; bool escaped = false; int phase = 1; QStringList phases; @@ -129,14 +129,14 @@ static int doSed(int argc, char **argv) } if (curr.contains(QLatin1Char('i'))) { curr.remove(QLatin1Char('i')); - matchcase = Qt::CaseInsensitive; + matchcase = QRegularExpression::CaseInsensitiveOption; } if (curr != QLatin1String("g")) { fprintf(stderr, "Error: sed s command supports only g & i options; g is required\n"); return 3; } SedSubst subst; - subst.from = QRegExp(phases.at(0), matchcase); + subst.from = QRegularExpression(phases.at(0), matchcase); subst.to = phases.at(1); subst.to.replace(QLatin1String("\\\\"), QLatin1String("\\")); // QString::replace(rx, sub) groks \1, but not \\. substs << subst; diff --git a/qmake/option.cpp b/qmake/option.cpp index 9ec2fe6411..2d5ef9dfd6 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -30,7 +30,7 @@ #include "cachekeys.h" #include <ioutils.h> #include <qdir.h> -#include <qregexp.h> +#include <qregularexpression.h> #include <qhash.h> #include <qdebug.h> #include <qlibraryinfo.h> @@ -519,12 +519,14 @@ Option::fixString(QString string, uchar flags) //fix the environment variables if(flags & Option::FixEnvVars) { - int rep; - static QRegExp reg_var("\\$\\(.*\\)"); - reg_var.setMinimal(true); - while((rep = reg_var.indexIn(string)) != -1) - string.replace(rep, reg_var.matchedLength(), - QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_var.matchedLength() - 3).toLatin1().constData()).constData())); + static QRegularExpression reg_var("\\$\\(.*\\)", QRegularExpression::InvertedGreedinessOption); + QRegularExpressionMatch match; + while ((match = reg_var.match(string)).hasMatch()) { + int start = match.capturedStart(); + int len = match.capturedLength(); + string.replace(start, len, + QString::fromLocal8Bit(qgetenv(string.mid(start + 2, len - 3).toLatin1().constData()).constData())); + } } //canonicalize it (and treat as a path) diff --git a/qmake/qmake.pro b/qmake/qmake.pro index 53e0811098..c64017f05b 100644 --- a/qmake/qmake.pro +++ b/qmake/qmake.pro @@ -10,6 +10,7 @@ DEFINES += \ PROEVALUATOR_FULL \ QT_BOOTSTRAPPED \ QT_BUILD_QMAKE \ + QT_USE_QSTRINGBUILDER \ QT_NO_FOREACH \ $$shell_quote(QT_VERSION_STR=\"$$QT_VERSION\") \ QT_VERSION_MAJOR=$$QT_MAJOR_VERSION \ @@ -102,11 +103,13 @@ INCLUDEPATH += \ VPATH += \ ../src/corelib/global \ + ../src/corelib/text \ ../src/corelib/tools \ ../src/corelib/kernel \ ../src/corelib/codecs \ ../src/corelib/plugin \ ../src/corelib/io \ + ../src/corelib/time \ ../src/corelib/serialization SOURCES += \ @@ -150,9 +153,11 @@ SOURCES += \ qmetatype.cpp \ qnumeric.cpp \ qregexp.cpp \ + qregularexpression.cpp \ qromancalendar.cpp \ qsettings.cpp \ qstring.cpp \ + qstringbuilder.cpp \ qstringlist.cpp \ qsystemerror.cpp \ qtemporaryfile.cpp \ @@ -207,8 +212,10 @@ HEADERS += \ qmetatype.h \ qnumeric.h \ qregexp.h \ + qregularexpression.h \ qromancalendar_p.h \ qstring.h \ + qstringbuilder.h \ qstringlist.h \ qstringmatcher.h \ qsystemerror_p.h \ @@ -221,6 +228,8 @@ HEADERS += \ qxmlstream.h \ qxmlutils_p.h +include(../src/3rdparty/pcre2/pcre2.pri) + unix { SOURCES += \ qcore_unix.cpp \ diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index 0185ad566c..c943acb602 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -106,11 +106,7 @@ #define QT_FEATURE_lttng -1 #define QT_NO_QOBJECT #define QT_FEATURE_process -1 -#ifndef QT_BUILD_QMAKE #define QT_FEATURE_regularexpression 1 -#else -#define QT_FEATURE_regularexpression -1 -#endif #ifdef __GLIBC_PREREQ # define QT_FEATURE_renameat2 (__GLIBC_PREREQ(2, 28) ? 1 : -1) #else diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp index 4aa16aaa71..f5ba691d72 100644 --- a/src/corelib/io/qurlidna.cpp +++ b/src/corelib/io/qurlidna.cpp @@ -2525,16 +2525,14 @@ QString qt_ACE_do(QStringView domain, AceOperation op, AceLeadingDot dot) result.resize(prevLen + labelLength); { QChar *out = result.data() + prevLen; - const QChar *in = domain.data() + lastIdx; - const QChar *e = in + labelLength; - for (; in < e; ++in, ++out) { - ushort uc = in->unicode(); + for (QChar c : domain.mid(lastIdx, labelLength)) { + const auto uc = c.unicode(); if (uc > 0x7f) simple = false; if (uc >= 'A' && uc <= 'Z') - *out = QChar(uc | 0x20); + *out++ = QChar(uc | 0x20); else - *out = *in; + *out++ = c; } } diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index f1d0dc859e..d65f1bdebd 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -48,7 +48,6 @@ #include <QtCore/QFile> #include <QtCore/QFileInfo> -#include <QtCore/QSet> #include <QtCore/QStandardPaths> #include <QtCore/QBuffer> #include <QtCore/QUrl> diff --git a/src/corelib/text/qchar.h b/src/corelib/text/qchar.h index fb358ba8be..8a616b4c73 100644 --- a/src/corelib/text/qchar.h +++ b/src/corelib/text/qchar.h @@ -42,6 +42,8 @@ #include <QtCore/qglobal.h> +#include <functional> // for std::hash + QT_BEGIN_NAMESPACE @@ -664,4 +666,17 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QChar &); QT_END_NAMESPACE +namespace std { +template <> +struct hash<QT_PREPEND_NAMESPACE(QChar)> +{ + template <typename = void> // for transparent constexpr tracking + constexpr size_t operator()(QT_PREPEND_NAMESPACE(QChar) c) const + noexcept(noexcept(std::hash<char16_t>{}(u' '))) + { + return std::hash<char16_t>{}(c.unicode()); + } +}; +} // namespace std + #endif // QCHAR_H diff --git a/src/corelib/text/qlocale_mac.mm b/src/corelib/text/qlocale_mac.mm index 5381f0f975..56a108c6e9 100644 --- a/src/corelib/text/qlocale_mac.mm +++ b/src/corelib/text/qlocale_mac.mm @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE static QByteArray envVarLocale() { - static QByteArray lang = 0; + static QByteArray lang; #ifdef Q_OS_UNIX lang = qgetenv("LC_ALL"); if (lang.isEmpty()) diff --git a/src/corelib/text/qregularexpression.cpp b/src/corelib/text/qregularexpression.cpp index 7ed8618e96..6b81f5cc79 100644 --- a/src/corelib/text/qregularexpression.cpp +++ b/src/corelib/text/qregularexpression.cpp @@ -1535,9 +1535,17 @@ QString QRegularExpression::errorString() const } while (errorStringLength < 0); errorString.resize(errorStringLength); +#ifdef QT_NO_TRANSLATION + return errorString; +#else return QCoreApplication::translate("QRegularExpression", std::move(errorString).toLatin1().constData()); +#endif } +#ifdef QT_NO_TRANSLATION + return QLatin1String("no error"); +#else return QCoreApplication::translate("QRegularExpression", "no error"); +#endif } /*! diff --git a/src/corelib/tools/qduplicatetracker_p.h b/src/corelib/tools/qduplicatetracker_p.h index 99068c01a3..cd57d4aed5 100644 --- a/src/corelib/tools/qduplicatetracker_p.h +++ b/src/corelib/tools/qduplicatetracker_p.h @@ -87,6 +87,18 @@ public: #endif return !inserted; } + Q_REQUIRED_RESULT bool hasSeen(T &&s) + { + bool inserted; +#ifdef __cpp_lib_memory_resource + inserted = set.insert(std::move(s)).second; +#else + set.insert(std::move(s)); + const int n = set.size(); + inserted = qExchange(setSize, n) != n; +#endif + return !inserted; + } }; QT_END_NAMESPACE diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp index bc76d0ea60..9bb9d57c4e 100644 --- a/src/gui/itemmodels/qstandarditemmodel.cpp +++ b/src/gui/itemmodels/qstandarditemmodel.cpp @@ -48,7 +48,7 @@ #include <QtCore/qstringlist.h> #include <QtCore/qbitarray.h> #include <QtCore/qmimedata.h> - +#include <private/qduplicatetracker_p.h> #include <private/qstandarditemmodel_p.h> #include <qdebug.h> #include <algorithm> @@ -3114,12 +3114,11 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const //remove duplicates childrens { - QSet<QStandardItem *> seen; + QDuplicateTracker<QStandardItem *> seen; while (!stack.isEmpty()) { QStandardItem *itm = stack.pop(); - if (seen.contains(itm)) + if (seen.hasSeen(itm)) continue; - seen.insert(itm); const QVector<QStandardItem*> &childList = itm->d_func()->children; for (int i = 0; i < childList.count(); ++i) { diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp index d636bca510..7178ef2928 100644 --- a/src/gui/text/qfontengine_qpf2.cpp +++ b/src/gui/text/qfontengine_qpf2.cpp @@ -44,6 +44,7 @@ #include <QtCore/QDir> #include <QtCore/QBuffer> #include <QtCore/private/qstringiterator_p.h> +#include <QtCore/private/qduplicatetracker_p.h> #include <QtGui/private/qpaintengine_raster_p.h> #include <QtGui/private/qguiapplication_p.h> @@ -346,7 +347,7 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp } #if defined(DEBUG_FONTENGINE) - QSet<QChar> seenGlyphs; + QDuplicateTracker<QChar> seenGlyphs; #endif int glyph_pos = 0; @@ -366,10 +367,8 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); #if 0 && defined(DEBUG_FONTENGINE) QChar c(uc); - if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) + if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.hasSeen(c)) qDebug() << "glyph for character" << c << '/' << Qt::hex << uc << "is" << Qt::dec << glyphs[glyph_pos].glyph; - - seenGlyphs.insert(c); #endif ++glyph_pos; } diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 4d0a9e3a7c..d0dade31ef 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1757,7 +1757,6 @@ inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line) return true; const QFixed oldTextWidth = line.textWidth; - minw = qMax(minw, tmpData.textWidth); line += tmpData; line.textWidth += spaceData.textWidth; @@ -1780,13 +1779,14 @@ inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line) static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &glyphCount, const QScriptItem ¤t, const unsigned short *logClusters, - const QGlyphLayout &glyphs) + const QGlyphLayout &glyphs, QFixed *clusterWidth = nullptr) { int glyphPosition = logClusters[pos]; do { // got to the first next cluster ++pos; ++line.length; } while (pos < end && logClusters[pos] == glyphPosition); + QFixed clusterWid = line.textWidth; do { // calculate the textWidth for the rest of the current cluster. if (!glyphs.attributes[glyphPosition].dontPrint) line.textWidth += glyphs.advances[glyphPosition]; @@ -1795,6 +1795,8 @@ static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &gly Q_ASSERT((pos == end && glyphPosition == current.num_glyphs) || logClusters[pos] == glyphPosition); + if (clusterWidth) + *clusterWidth += (line.textWidth - clusterWid); ++glyphCount; } @@ -1821,6 +1823,7 @@ void QTextLine::layout_helper(int maxGlyphs) QTextOption::WrapMode wrapMode = eng->option.wrapMode(); bool breakany = (wrapMode == QTextOption::WrapAnywhere); + const bool breakWordOrAny = breakany || (wrapMode == QTextOption::WrapAtWordBoundaryOrAnywhere); lbh.manualWrap = (wrapMode == QTextOption::ManualWrap || wrapMode == QTextOption::NoWrap); int item = -1; @@ -1957,9 +1960,10 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.whiteSpaceOrObject = false; bool sb_or_ws = false; lbh.saveCurrentGlyph(); + QFixed accumulatedTextWidth; do { addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, - current, lbh.logClusters, lbh.glyphs); + current, lbh.logClusters, lbh.glyphs, &accumulatedTextWidth); // This is a hack to fix a regression caused by the introduction of the // whitespace flag to non-breakable spaces and will cause the non-breakable @@ -1975,11 +1979,16 @@ void QTextLine::layout_helper(int maxGlyphs) || attributes[lbh.currentPosition].lineBreak) { sb_or_ws = true; break; - } else if (breakany && attributes[lbh.currentPosition].graphemeBoundary) { - break; + } else if (attributes[lbh.currentPosition].graphemeBoundary) { + if (breakWordOrAny) { + lbh.minw = qMax(accumulatedTextWidth, lbh.minw); + accumulatedTextWidth = 0; + } + if (breakany) + break; } } while (lbh.currentPosition < end); - lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw); + lbh.minw = qMax(accumulatedTextWidth, lbh.minw); if (lbh.currentPosition > 0 && lbh.currentPosition <= end && (lbh.currentPosition == end || attributes[lbh.currentPosition].lineBreak) @@ -2106,6 +2115,20 @@ found: line.descent.toReal(), line.textWidth.toReal(), lbh.spaceData.width.toReal()); LB_DEBUG(" : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data()); + const QFixed trailingSpace = (eng->option.flags() & QTextOption::IncludeTrailingSpaces + ? lbh.spaceData.textWidth + : QFixed(0)); + if (eng->option.wrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere) { + if ((lbh.maxGlyphs != INT_MAX && lbh.glyphCount > lbh.maxGlyphs) + || (lbh.maxGlyphs == INT_MAX && line.textWidth > (line.width - trailingSpace))) { + + eng->option.setWrapMode(QTextOption::WrapAnywhere); + layout_helper(lbh.maxGlyphs); + eng->option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + return; + } + } + if (lbh.manualWrap) { eng->minWidth = qMax(eng->minWidth, line.textWidth); eng->maxWidth = qMax(eng->maxWidth, line.textWidth); @@ -2116,8 +2139,8 @@ found: if (line.textWidth > 0 && item < eng->layoutData->items.size()) eng->maxWidth += lbh.spaceData.textWidth; - if (eng->option.flags() & QTextOption::IncludeTrailingSpaces) - line.textWidth += lbh.spaceData.textWidth; + + line.textWidth += trailingSpace; if (lbh.spaceData.length) { line.trailingSpaces = lbh.spaceData.length; line.hasTrailingSpaces = true; @@ -2125,18 +2148,6 @@ found: line.justified = false; line.gridfitted = false; - - if (eng->option.wrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere) { - if ((lbh.maxGlyphs != INT_MAX && lbh.glyphCount > lbh.maxGlyphs) - || (lbh.maxGlyphs == INT_MAX && line.textWidth > line.width)) { - - eng->option.setWrapMode(QTextOption::WrapAnywhere); - line.length = 0; - line.textWidth = 0; - layout_helper(lbh.maxGlyphs); - eng->option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); - } - } } /*! diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 949a2e075a..dbe75ebe51 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -39,6 +39,7 @@ // for normalizeTypeInternal #include <private/qmetaobject_moc_p.h> +#include <private/qduplicatetracker_p.h> QT_BEGIN_NAMESPACE @@ -1868,14 +1869,13 @@ void Moc::checkProperties(ClassDef *cdef) // specify get function, for compatibiliy we accept functions // returning pointers, or const char * for QByteArray. // - QSet<QByteArray> definedProperties; + QDuplicateTracker<QByteArray> definedProperties; for (int i = 0; i < cdef->propertyList.count(); ++i) { PropertyDef &p = cdef->propertyList[i]; - if (definedProperties.contains(p.name)) { + if (definedProperties.hasSeen(p.name)) { QByteArray msg = "The property '" + p.name + "' is defined multiple times in class " + cdef->classname + "."; warning(msg.constData()); } - definedProperties.insert(p.name); if (p.read.isEmpty() && p.member.isEmpty()) { if (!cdef->qPropertyMembers.contains(p.name) && !p.isQProperty) { diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 857ca31529..158521e13f 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -1580,7 +1580,11 @@ void QMainWindowLayout::setTabShape(QTabWidget::TabShape tabShape) QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) const { - return tabPositions[toDockPos(area)]; + const auto dockPos = toDockPos(area); + if (dockPos < QInternal::DockCount) + return tabPositions[dockPos]; + qWarning("QMainWindowLayout::tabPosition called with out-of-bounds value '%d'", int(area)); + return QTabWidget::North; } void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition) diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h index d4f0bd4517..ab95258e78 100644 --- a/src/widgets/widgets/qmainwindowlayout_p.h +++ b/src/widgets/widgets/qmainwindowlayout_p.h @@ -523,7 +523,7 @@ public: int sep; // separator extent #if QT_CONFIG(tabwidget) - QTabWidget::TabPosition tabPositions[4]; + QTabWidget::TabPosition tabPositions[QInternal::DockCount]; QTabWidget::TabShape _tabShape; QTabWidget::TabShape tabShape() const; diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp index fcd227f1bf..b2ec6e1c1c 100644 --- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp +++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp @@ -309,6 +309,13 @@ void tst_QHashFunctions::stdHash() QCOMPARE(s.size(), 2UL); } + { + std::unordered_set<QChar> s = {u'H', u'W'}; + QCOMPARE(s.size(), 2UL); + s.insert(u'H'); + QCOMPARE(s.size(), 2UL); + } + } void tst_QHashFunctions::setGlobalQHashSeed() diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index 8466305832..9c5b58884a 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -142,6 +142,7 @@ private slots: void koreanWordWrap(); void tooManyDirectionalCharctersCrash_qtbug77819(); void softHyphens(); + void min_maximumWidth(); private: QFont testFont; @@ -2488,5 +2489,41 @@ void tst_QTextLayout::softHyphens() } } +void tst_QTextLayout::min_maximumWidth() +{ + QString longString("lmong_long_crazy_87235982735_23857239682376923876923876-fuwhfhfw-names-AAAA-deeaois2019-03-03.and.more"); + QTextLayout layout(longString, testFont); + + for (int wrapMode = QTextOption::NoWrap; wrapMode <= QTextOption::WrapAtWordBoundaryOrAnywhere; ++wrapMode) { + QTextOption opt; + opt.setWrapMode((QTextOption::WrapMode)wrapMode); + layout.setTextOption(opt); + layout.beginLayout(); + while (layout.createLine().isValid()) { } + layout.endLayout(); + const qreal minWidth = layout.minimumWidth(); + const qreal maxWidth = layout.maximumWidth(); + + // Try the layout from slightly wider than the widest (maxWidth) + // and narrow it down to slighly narrower than minWidth + // layout.maximumWidth() should return the same regardless + qreal width = qCeil(maxWidth/10)*10 + 10; // begin a bit wider + const qreal stepSize = 20; + while (width >= minWidth - stepSize) { + layout.beginLayout(); + for (;;) { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + line.setLineWidth(width); + } + layout.endLayout(); + QCOMPARE(layout.minimumWidth(), minWidth); + QCOMPARE(layout.maximumWidth(), maxWidth); + width -= stepSize; + } + } +} + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" diff --git a/tests/auto/tools/qmakelib/CMakeLists.txt b/tests/auto/tools/qmakelib/CMakeLists.txt index 1e56c81e77..abb8e62c95 100644 --- a/tests/auto/tools/qmakelib/CMakeLists.txt +++ b/tests/auto/tools/qmakelib/CMakeLists.txt @@ -21,6 +21,7 @@ add_qt_test(tst_qmakelib PROEVALUATOR_FULL PROEVALUATOR_SETENV PROPARSER_DEBUG + QT_USE_QSTRINGBUILDER INCLUDE_DIRECTORIES ../../../../qmake/library ) diff --git a/tests/auto/tools/qmakelib/qmakelib.pro b/tests/auto/tools/qmakelib/qmakelib.pro index 5e9e9fe637..0e39d3115e 100644 --- a/tests/auto/tools/qmakelib/qmakelib.pro +++ b/tests/auto/tools/qmakelib/qmakelib.pro @@ -22,4 +22,4 @@ SOURCES += \ qmakebuiltins.cpp \ qmakeevaluator.cpp -DEFINES += PROPARSER_DEBUG PROEVALUATOR_FULL PROEVALUATOR_SETENV +DEFINES += PROPARSER_DEBUG PROEVALUATOR_FULL PROEVALUATOR_SETENV QT_USE_QSTRINGBUILDER |