From 923c4c950224721fb323d38af5952abe0b09d26c Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 2 Aug 2024 13:43:38 +0200 Subject: [PATCH 1/7] QtKeychain: Remove deprecated gnome-keyring support Gnome-keyring tends to crash when available. Recent versions of linux do not provide it anymore. Therefor we remove the code and make libsecrets the default instead. Change-Id: I6aeb9400eca3fcad340f150b67f68e94a0db25f2 Reviewed-by: Jarek Kobus Reviewed-by: Marcus Tillmanns Reviewed-by: hjk Reviewed-by: Christian Stenger Reviewed-by: Mohammad Mehdi Salem Naraghi --- src/libs/3rdparty/qtkeychain/CMakeLists.txt | 1 - src/libs/3rdparty/qtkeychain/gnomekeyring.cpp | 86 ------------ src/libs/3rdparty/qtkeychain/gnomekeyring_p.h | 94 ------------- .../3rdparty/qtkeychain/keychain_unix.cpp | 125 +----------------- src/libs/3rdparty/qtkeychain/qtkeychain.qbs | 2 - 5 files changed, 2 insertions(+), 306 deletions(-) delete mode 100644 src/libs/3rdparty/qtkeychain/gnomekeyring.cpp delete mode 100644 src/libs/3rdparty/qtkeychain/gnomekeyring_p.h diff --git a/src/libs/3rdparty/qtkeychain/CMakeLists.txt b/src/libs/3rdparty/qtkeychain/CMakeLists.txt index 7b2cc6d88f8..42a504b0b7e 100644 --- a/src/libs/3rdparty/qtkeychain/CMakeLists.txt +++ b/src/libs/3rdparty/qtkeychain/CMakeLists.txt @@ -58,7 +58,6 @@ if (UNIX AND NOT APPLE) DEFINES KEYCHAIN_DBUS=1 DEPENDS Qt::DBus SOURCES - gnomekeyring.cpp keychain_unix.cpp libsecret.cpp plaintextstore.cpp diff --git a/src/libs/3rdparty/qtkeychain/gnomekeyring.cpp b/src/libs/3rdparty/qtkeychain/gnomekeyring.cpp deleted file mode 100644 index 6347052dcbf..00000000000 --- a/src/libs/3rdparty/qtkeychain/gnomekeyring.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "gnomekeyring_p.h" - -const char* GnomeKeyring::GNOME_KEYRING_DEFAULT = nullptr; - -bool GnomeKeyring::isAvailable() -{ - const GnomeKeyring& keyring = instance(); - return keyring.isLoaded() && - keyring.NETWORK_PASSWORD && - keyring.is_available && - keyring.find_password && - keyring.store_password && - keyring.delete_password && - keyring.is_available(); -} - -GnomeKeyring::gpointer GnomeKeyring::store_network_password( - const gchar* keyring, - const gchar* display_name, - const gchar* user, - const gchar* server, - const gchar* type, - const gchar* password, - OperationDoneCallback callback, - gpointer data, - GDestroyNotify destroy_data ) -{ - if ( !isAvailable() ) - return 0; - return instance().store_password( instance().NETWORK_PASSWORD, - keyring, display_name, password, callback, - data, destroy_data, - "user", user, - "server", server, - "type", type, - static_cast(0) ); -} - -GnomeKeyring::gpointer GnomeKeyring::find_network_password( - const gchar* user, const gchar* server, const gchar* type, - OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data ) -{ - if ( !isAvailable() ) - return 0; - - return instance().find_password( instance().NETWORK_PASSWORD, - callback, data, destroy_data, - "user", user, "server", server, "type", type, - static_cast(0) ); -} - -GnomeKeyring::gpointer GnomeKeyring::delete_network_password( const gchar* user, - const gchar* server, - OperationDoneCallback callback, - gpointer data, - GDestroyNotify destroy_data ) -{ - if ( !isAvailable() ) - return 0; - return instance().delete_password( instance().NETWORK_PASSWORD, - callback, data, destroy_data, - "user", user, "server", server, static_cast(0) ); -} - -GnomeKeyring::GnomeKeyring() - : QLibrary(QLatin1String("gnome-keyring"), 0) -{ - static const PasswordSchema schema = { - ITEM_NETWORK_PASSWORD, - {{ "user", ATTRIBUTE_TYPE_STRING }, - { "server", ATTRIBUTE_TYPE_STRING }, - { "type", ATTRIBUTE_TYPE_STRING }, - { 0, static_cast( 0 ) }} - }; - - NETWORK_PASSWORD = &schema; - is_available = reinterpret_cast( resolve( "gnome_keyring_is_available" ) ); - find_password = reinterpret_cast( resolve( "gnome_keyring_find_password" ) ); - store_password = reinterpret_cast( resolve( "gnome_keyring_store_password" ) ); - delete_password = reinterpret_cast( resolve( "gnome_keyring_delete_password" ) ); -} - -GnomeKeyring& GnomeKeyring::instance() { - static GnomeKeyring keyring; - return keyring; -} diff --git a/src/libs/3rdparty/qtkeychain/gnomekeyring_p.h b/src/libs/3rdparty/qtkeychain/gnomekeyring_p.h deleted file mode 100644 index 87c062c375a..00000000000 --- a/src/libs/3rdparty/qtkeychain/gnomekeyring_p.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef QTKEYCHAIN_GNOME_P_H -#define QTKEYCHAIN_GNOME_P_H - -#include - -class GnomeKeyring : private QLibrary { - Q_OBJECT - -public: - enum Result { - RESULT_OK, - RESULT_DENIED, - RESULT_NO_KEYRING_DAEMON, - RESULT_ALREADY_UNLOCKED, - RESULT_NO_SUCH_KEYRING, - RESULT_BAD_ARGUMENTS, - RESULT_IO_ERROR, - RESULT_CANCELLED, - RESULT_KEYRING_ALREADY_EXISTS, - RESULT_NO_MATCH - }; - - enum ItemType { - ITEM_GENERIC_SECRET = 0, - ITEM_NETWORK_PASSWORD, - ITEM_NOTE, - ITEM_CHAINED_KEYRING_PASSWORD, - ITEM_ENCRYPTION_KEY_PASSWORD, - ITEM_PK_STORAGE = 0x100 - }; - - enum AttributeType { - ATTRIBUTE_TYPE_STRING, - ATTRIBUTE_TYPE_UINT32 - }; - - typedef char gchar; - typedef void* gpointer; - typedef bool gboolean; - typedef struct { - ItemType item_type; - struct { - const gchar* name; - AttributeType type; - } attributes[32]; - } PasswordSchema; - - typedef void ( *OperationGetStringCallback )( Result result, bool binary, - const char* string, gpointer data ); - typedef void ( *OperationDoneCallback )( Result result, gpointer data ); - typedef void ( *GDestroyNotify )( gpointer data ); - - static const char* GNOME_KEYRING_DEFAULT; - - static bool isAvailable(); - - static gpointer store_network_password( const gchar* keyring, const gchar* display_name, - const gchar* user, const gchar* server, - const gchar* type, const gchar* password, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ); - - static gpointer find_network_password( const gchar* user, const gchar* server, - const gchar* type, - OperationGetStringCallback callback, - gpointer data, GDestroyNotify destroy_data ); - - static gpointer delete_network_password( const gchar* user, const gchar* server, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ); -private: - GnomeKeyring(); - - static GnomeKeyring& instance(); - - const PasswordSchema* NETWORK_PASSWORD; - typedef gboolean ( is_available_fn )( void ); - typedef gpointer ( store_password_fn )( const PasswordSchema* schema, const gchar* keyring, - const gchar* display_name, const gchar* password, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data, - ... ); - typedef gpointer ( find_password_fn )( const PasswordSchema* schema, - OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data, - ... ); - typedef gpointer ( delete_password_fn )( const PasswordSchema* schema, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data, - ... ); - - is_available_fn* is_available; - find_password_fn* find_password; - store_password_fn* store_password; - delete_password_fn* delete_password; -}; - - -#endif diff --git a/src/libs/3rdparty/qtkeychain/keychain_unix.cpp b/src/libs/3rdparty/qtkeychain/keychain_unix.cpp index a3e83a96875..9a54dcf948e 100644 --- a/src/libs/3rdparty/qtkeychain/keychain_unix.cpp +++ b/src/libs/3rdparty/qtkeychain/keychain_unix.cpp @@ -7,7 +7,6 @@ * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #include "keychain_p.h" -#include "gnomekeyring_p.h" #include "libsecret_p.h" #include "plaintextstore_p.h" @@ -17,7 +16,6 @@ using namespace QKeychain; enum KeyringBackend { Backend_LibSecretKeyring, - Backend_GnomeKeyring, Backend_Kwallet4, Backend_Kwallet5, Backend_Kwallet6, @@ -135,9 +133,6 @@ static KeyringBackend detectKeyringBackend() if (LibSecretKeyring::isAvailable()) { return Backend_LibSecretKeyring; } - if (GnomeKeyring::isAvailable()) { - return Backend_GnomeKeyring; - } // During startup the keychain backend might just not have started yet return Backend_Kwallet5; @@ -148,9 +143,6 @@ static KeyringBackend detectKeyringBackend() if (LibSecretKeyring::isAvailable()) { return Backend_LibSecretKeyring; } - if (GnomeKeyring::isAvailable()) { - return Backend_GnomeKeyring; - } // During startup the keychain backend might just not have started yet return Backend_Kwallet6; @@ -162,9 +154,6 @@ static KeyringBackend detectKeyringBackend() if (LibSecretKeyring::isAvailable()) { return Backend_LibSecretKeyring; } - if (GnomeKeyring::isAvailable()) { - return Backend_GnomeKeyring; - } if (isKwalletAvailable(KWALLET6_DBUS_IFACE, KWALLET6_DBUS_PATH)) { return Backend_Kwallet6; } @@ -180,7 +169,7 @@ static KeyringBackend detectKeyringBackend() // // In the future there should be a difference between "API available" and // "keychain available". - return Backend_GnomeKeyring; + return Backend_LibSecretKeyring; } } @@ -214,16 +203,6 @@ void ReadPasswordJobPrivate::scheduledStart() { q->emitFinishedWithError( OtherError, tr("Unknown error") ); } } break; - case Backend_GnomeKeyring: - this->mode = JobPrivate::Text; - if ( !GnomeKeyring::find_network_password( key.toUtf8().constData(), - q->service().toUtf8().constData(), - "plaintext", - reinterpret_cast( &JobPrivate::gnomeKeyring_readCb ), - this, 0 ) ) - q->emitFinishedWithError( OtherError, tr("Unknown error") ); - break; - case Backend_Kwallet4: kwalletReadPasswordScheduledStartImpl(KWALLET4_DBUS_IFACE, KWALLET4_DBUS_PATH, this); break; @@ -246,59 +225,6 @@ void JobPrivate::kwalletWalletFound(QDBusPendingCallWatcher *watcher) this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) ); } -static QPair mapGnomeKeyringError( int result ) -{ - Q_ASSERT( result != GnomeKeyring::RESULT_OK ); - - switch ( result ) { - case GnomeKeyring::RESULT_DENIED: - return qMakePair( AccessDenied, QObject::tr("Access to keychain denied") ); - case GnomeKeyring::RESULT_NO_KEYRING_DAEMON: - return qMakePair( NoBackendAvailable, QObject::tr("No keyring daemon") ); - case GnomeKeyring::RESULT_ALREADY_UNLOCKED: - return qMakePair( OtherError, QObject::tr("Already unlocked") ); - case GnomeKeyring::RESULT_NO_SUCH_KEYRING: - return qMakePair( OtherError, QObject::tr("No such keyring") ); - case GnomeKeyring::RESULT_BAD_ARGUMENTS: - return qMakePair( OtherError, QObject::tr("Bad arguments") ); - case GnomeKeyring::RESULT_IO_ERROR: - return qMakePair( OtherError, QObject::tr("I/O error") ); - case GnomeKeyring::RESULT_CANCELLED: - return qMakePair( OtherError, QObject::tr("Cancelled") ); - case GnomeKeyring::RESULT_KEYRING_ALREADY_EXISTS: - return qMakePair( OtherError, QObject::tr("Keyring already exists") ); - case GnomeKeyring::RESULT_NO_MATCH: - return qMakePair( EntryNotFound, QObject::tr("No match") ); - default: - break; - } - - return qMakePair( OtherError, QObject::tr("Unknown error") ); -} - -void JobPrivate::gnomeKeyring_readCb( int result, const char* string, JobPrivate* self ) -{ - if ( result == GnomeKeyring::RESULT_OK ) { - if (self->mode == JobPrivate::Text) - self->data = QByteArray(string); - else - self->data = QByteArray::fromBase64(string); - - self->q->emitFinished(); - } else if (self->mode == JobPrivate::Text) { - self->mode = JobPrivate::Binary; - if ( !GnomeKeyring::find_network_password( self->key.toUtf8().constData(), - self->q->service().toUtf8().constData(), - "base64", - reinterpret_cast( &JobPrivate::gnomeKeyring_readCb ), - self, 0 ) ) - self->q->emitFinishedWithError( OtherError, tr("Unknown error") ); - } else { - const QPair errorResult = mapGnomeKeyringError( result ); - self->q->emitFinishedWithError( errorResult.first, errorResult.second ); - } -} - void ReadPasswordJobPrivate::fallbackOnError(const QDBusError& err ) { PlainTextStore plainTextStore( q->service(), q->settings() ); @@ -455,34 +381,6 @@ void WritePasswordJobPrivate::scheduledStart() { q->emitFinishedWithError( OtherError, tr("Unknown error") ); } } break; - case Backend_GnomeKeyring: { - QString type; - QByteArray password; - - switch(mode) { - case JobPrivate::Text: - type = QLatin1String("plaintext"); - password = data; - break; - default: - type = QLatin1String("base64"); - password = data.toBase64(); - break; - } - - QByteArray service = q->service().toUtf8(); - if ( !GnomeKeyring::store_network_password( GnomeKeyring::GNOME_KEYRING_DEFAULT, - service.constData(), - key.toUtf8().constData(), - service.constData(), - type.toUtf8().constData(), - password.constData(), - reinterpret_cast( &JobPrivate::gnomeKeyring_writeCb ), - this, 0 ) ) - q->emitFinishedWithError( OtherError, tr("Unknown error") ); - } - break; - case Backend_Kwallet4: kwalletWritePasswordScheduledStart(KWALLET4_DBUS_IFACE, KWALLET4_DBUS_PATH, this); break; @@ -511,16 +409,6 @@ void WritePasswordJobPrivate::fallbackOnError(const QDBusError &err) q->emitFinished(); } -void JobPrivate::gnomeKeyring_writeCb(int result, JobPrivate* self ) -{ - if ( result == GnomeKeyring::RESULT_OK ) { - self->q->emitFinished(); - } else { - const QPair errorResult = mapGnomeKeyringError( result ); - self->q->emitFinishedWithError( errorResult.first, errorResult.second ); - } -} - void JobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) { watcher->deleteLater(); QDBusPendingReply reply = *watcher; @@ -585,15 +473,6 @@ void DeletePasswordJobPrivate::scheduledStart() { q->emitFinishedWithError( OtherError, tr("Unknown error") ); } } break; - case Backend_GnomeKeyring: { - if ( !GnomeKeyring::delete_network_password( - key.toUtf8().constData(), q->service().toUtf8().constData(), - reinterpret_cast( &JobPrivate::gnomeKeyring_writeCb ), - this, 0 ) ) - q->emitFinishedWithError( OtherError, tr("Unknown error") ); - } - break; - case Backend_Kwallet4: kwalletWritePasswordScheduledStart(KWALLET4_DBUS_IFACE, KWALLET4_DBUS_PATH, this); break; @@ -627,7 +506,7 @@ void DeletePasswordJobPrivate::fallbackOnError(const QDBusError &err) { bool QKeychain::isAvailable() { - return LibSecretKeyring::isAvailable() || GnomeKeyring::isAvailable() + return LibSecretKeyring::isAvailable() || isKwalletAvailable(KWALLET6_DBUS_IFACE, KWALLET6_DBUS_PATH) || isKwalletAvailable(KWALLET5_DBUS_IFACE, KWALLET5_DBUS_PATH); } diff --git a/src/libs/3rdparty/qtkeychain/qtkeychain.qbs b/src/libs/3rdparty/qtkeychain/qtkeychain.qbs index b5f8e7dc131..96c6cb72a76 100644 --- a/src/libs/3rdparty/qtkeychain/qtkeychain.qbs +++ b/src/libs/3rdparty/qtkeychain/qtkeychain.qbs @@ -74,8 +74,6 @@ QtcLibrary { cpp.defines: outer.concat(["KEYCHAIN_DBUS=1"]) cpp.cxxFlags: outer.concat("-Wno-cast-function-type") files: [ - "gnomekeyring.cpp", - "gnomekeyring_p.h", "keychain_unix.cpp", "libsecret.cpp", "libsecret_p.h", From 170c7d4ead8217e0f7ee70241d09997452bd43ba Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 7 Aug 2024 14:01:01 +0200 Subject: [PATCH 2/7] Bump version to 14.0.2 Change-Id: Idd9ae9a13cd3b34bf1f2c62a644342b673d56a54 Reviewed-by: Eike Ziller --- cmake/QtCreatorIDEBranding.cmake | 4 ++-- qbs/modules/qtc/qtc.qbs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/QtCreatorIDEBranding.cmake b/cmake/QtCreatorIDEBranding.cmake index 20773c71ac1..beb3e8f0364 100644 --- a/cmake/QtCreatorIDEBranding.cmake +++ b/cmake/QtCreatorIDEBranding.cmake @@ -1,6 +1,6 @@ -set(IDE_VERSION "14.0.1") # The IDE version. +set(IDE_VERSION "14.0.2") # The IDE version. set(IDE_VERSION_COMPAT "14.0.0") # The IDE Compatibility version. -set(IDE_VERSION_DISPLAY "14.0.1") # The IDE display version. +set(IDE_VERSION_DISPLAY "14.0.2") # The IDE display version. set(IDE_COPYRIGHT_YEAR "2024") # The IDE current copyright year. set(IDE_SETTINGSVARIANT "QtProject") # The IDE settings variation. diff --git a/qbs/modules/qtc/qtc.qbs b/qbs/modules/qtc/qtc.qbs index 31efc8b456a..86484cdef70 100644 --- a/qbs/modules/qtc/qtc.qbs +++ b/qbs/modules/qtc/qtc.qbs @@ -4,10 +4,10 @@ import qbs.FileInfo import qbs.Utilities Module { - property string qtcreator_display_version: '14.0.1' + property string qtcreator_display_version: '14.0.2' property string ide_version_major: '14' property string ide_version_minor: '0' - property string ide_version_release: '1' + property string ide_version_release: '2' property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.' + ide_version_release From 9f05f67711322c1f592ccdb5627af223b16c5534 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 7 Aug 2024 14:59:55 +0200 Subject: [PATCH 3/7] CppEditor: Re-apply bugfix The original fix for this issue was reverted in 5d8f13bfd4e7d82291db930f22f9315efe28a120. Fixes: QTCREATORBUG-27547 Change-Id: Ifc0509b368ff3e9ca76e3273104c8ad447633165 Reviewed-by: Christian Stenger --- .../cppeditor/quickfixes/cppcodegenerationquickfixes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/cppeditor/quickfixes/cppcodegenerationquickfixes.cpp b/src/plugins/cppeditor/quickfixes/cppcodegenerationquickfixes.cpp index 7adf62cb815..6b54a5e9e63 100644 --- a/src/plugins/cppeditor/quickfixes/cppcodegenerationquickfixes.cpp +++ b/src/plugins/cppeditor/quickfixes/cppcodegenerationquickfixes.cpp @@ -1886,7 +1886,7 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d FullySpecifiedType memberVariableType = data.declarationSymbol->type(); memberVariableType.setConst(false); - const bool isMemberVariableStatic = memberVariableType.isStatic(); + const bool isMemberVariableStatic = data.declarationSymbol->isStatic(); memberVariableType.setStatic(false); Overview overview = CppCodeStyleSettings::currentProjectCodeStyleOverview(); overview.showTemplateParameters = false; From 61931fd709fafef12fa8f3d88578da83f4f9d986 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 7 Aug 2024 15:27:19 +0200 Subject: [PATCH 4/7] RemoteLinux: Change default rsync flags The -a flag implies some things we don't want. Fixes: QTCREATORBUG-31138 Change-Id: Ie662069bfc5e4b9464d9a17379d6c50fef3cad25 Reviewed-by: Christian Stenger --- src/plugins/projectexplorer/devicesupport/filetransfer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/devicesupport/filetransfer.cpp b/src/plugins/projectexplorer/devicesupport/filetransfer.cpp index b31a8f44280..acf57f68ac7 100644 --- a/src/plugins/projectexplorer/devicesupport/filetransfer.cpp +++ b/src/plugins/projectexplorer/devicesupport/filetransfer.cpp @@ -18,7 +18,7 @@ namespace ProjectExplorer { QString FileTransferSetupData::defaultRsyncFlags() { - return "-av"; + return "-rltv"; } static IDeviceConstPtr matchedDevice(const FilesToTransfer &files) From dceabc0e0a84fc96005ae8a341eb96a0fcfb5429 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 7 Aug 2024 13:14:02 +0200 Subject: [PATCH 5/7] CPlusPlus: Allow empty argument list in member initialization Fixes: QTCREATORBUG-30797 Change-Id: I6de0f05e071a5e73317d7a8e3d035e23e23a41aa Reviewed-by: Christian Stenger --- src/libs/3rdparty/cplusplus/Parser.cpp | 19 +++++++++---------- src/libs/3rdparty/cplusplus/Parser.h | 2 +- tests/auto/cplusplus/ast/tst_ast.cpp | 9 +++++++++ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 30e3fe0be1b..a9883267cc1 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -20,7 +20,6 @@ #include "Parser.h" #include "Token.h" -#include "Lexer.h" #include "Control.h" #include "AST.h" #include "Literals.h" @@ -30,7 +29,6 @@ #include #include -#include #include // for putchar #if defined(__INTEL_COMPILER) && !defined(va_copy) @@ -3088,7 +3086,7 @@ bool Parser::parseInitializer0x(ExpressionAST *&node, int *equals_token) } else if (LA() == T_LPAREN) { - return parseExpressionListParen(node); + return parseExpressionListParen(node, false); } return false; @@ -3258,7 +3256,7 @@ bool Parser::parseMemInitializer(MemInitializerListAST *&node) ast->name = name; if (LA() == T_LPAREN) { - parseExpressionListParen(ast->expression); + parseExpressionListParen(ast->expression, true); } else if (_languageFeatures.cxx11Enabled && LA() == T_LBRACE) { parseBracedInitList0x(ast->expression); } else { @@ -5452,7 +5450,7 @@ bool Parser::parseTypenameCallExpression(ExpressionAST *&node) ast->typename_token = typename_token; ast->name = name; if (LA() == T_LPAREN) { - parseExpressionListParen(ast->expression); + parseExpressionListParen(ast->expression, false); } else { // T_LBRACE parseBracedInitList0x(ast->expression); } @@ -5511,7 +5509,7 @@ bool Parser::parseCorePostfixExpression(ExpressionAST *&node) (LA() == T_LPAREN || (_languageFeatures.cxx11Enabled && LA() == T_LBRACE))) { ExpressionAST *expr = nullptr; if (LA() == T_LPAREN) { - parseExpressionListParen(expr); + parseExpressionListParen(expr, false); } else { // T_LBRACE parseBracedInitList0x(expr); } @@ -5707,13 +5705,14 @@ bool Parser::parseUnaryExpression(ExpressionAST *&node) } // new-placement ::= T_LPAREN expression-list T_RPAREN -bool Parser::parseExpressionListParen(ExpressionAST *&node) +bool Parser::parseExpressionListParen(ExpressionAST *&node, bool allowEmpty) { DEBUG_THIS_RULE(); if (LA() == T_LPAREN) { int lparen_token = consumeToken(); ExpressionListAST *expression_list = nullptr; - if (parseExpressionList(expression_list) && LA() == T_RPAREN) { + const bool hasList = parseExpressionList(expression_list); + if ((hasList || allowEmpty) && LA() == T_RPAREN) { int rparen_token = consumeToken(); ExpressionListParenAST *ast = new (_pool) ExpressionListParenAST; ast->lparen_token = lparen_token; @@ -5746,7 +5745,7 @@ bool Parser::parseNewExpression(ExpressionAST *&node) ExpressionAST *parenExpressionList = nullptr; - if (parseExpressionListParen(parenExpressionList)) { + if (parseExpressionListParen(parenExpressionList, false)) { int after_new_placement = cursor(); NewTypeIdAST *new_type_id = nullptr; @@ -5839,7 +5838,7 @@ bool Parser::parseNewInitializer(ExpressionAST *&node) { DEBUG_THIS_RULE(); if (LA() == T_LPAREN) - return parseExpressionListParen(node); + return parseExpressionListParen(node, false); else if (_languageFeatures.cxx11Enabled && LA() == T_LBRACE) return parseBracedInitList0x(node); return false; diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index e34a4ff5223..7c19c6d0ad6 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -117,7 +117,7 @@ public: bool parseNamespaceAliasDefinition(DeclarationAST *&node); bool parseNewArrayDeclarator(NewArrayDeclaratorListAST *&node); bool parseNewExpression(ExpressionAST *&node); - bool parseExpressionListParen(ExpressionAST *&node); + bool parseExpressionListParen(ExpressionAST *&node, bool allowEmpty); bool parseNewInitializer(ExpressionAST *&node); bool parseNewTypeId(NewTypeIdAST *&node); bool parseOperator(OperatorAST *&node); diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 15bc2f23192..3ded1a22003 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -112,6 +112,7 @@ private slots: void templated_dtor_3(); void templated_dtor_4(); void templated_dtor_5(); + void emptyMemberInitialization(); // possible declaration-or-expression statements void call_call_1(); @@ -2061,6 +2062,14 @@ void tst_AST::invalidFunctionInitializer() QVERIFY(diag.errorCount != 0); } +void tst_AST::emptyMemberInitialization() +{ + const std::shared_ptr unit(parse( + "struct S\n{\n S(): i() {}\n int i;};", TranslationUnit::ParseTranlationUnit)); + QVERIFY(unit->ast()); + QCOMPARE(diag.errorCount, 0); +} + void tst_AST::initTestCase() { control.setDiagnosticClient(&diag); From 9a8cba372b9b5877dbce2740a9d6845e4738f7b9 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 7 Aug 2024 14:01:50 +0200 Subject: [PATCH 6/7] CPlusPlus: Allow empty initializer lists in placement new Fixes: QTCREATORBUG-30798 Change-Id: Ib9945e4e721aca5f88665bd8a289ae3c54c69e65 Reviewed-by: Christian Stenger --- src/libs/3rdparty/cplusplus/Parser.cpp | 2 +- tests/auto/cplusplus/ast/tst_ast.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index a9883267cc1..473090b8818 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -5838,7 +5838,7 @@ bool Parser::parseNewInitializer(ExpressionAST *&node) { DEBUG_THIS_RULE(); if (LA() == T_LPAREN) - return parseExpressionListParen(node, false); + return parseExpressionListParen(node, true); else if (_languageFeatures.cxx11Enabled && LA() == T_LBRACE) return parseBracedInitList0x(node); return false; diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 3ded1a22003..497ececbcff 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -113,6 +113,7 @@ private slots: void templated_dtor_4(); void templated_dtor_5(); void emptyMemberInitialization(); + void placementNewWithEmptyConstructorArgs(); // possible declaration-or-expression statements void call_call_1(); @@ -2070,6 +2071,15 @@ void tst_AST::emptyMemberInitialization() QCOMPARE(diag.errorCount, 0); } +void tst_AST::placementNewWithEmptyConstructorArgs() +{ + const std::shared_ptr unit(parse( + "int main()\n{ int* i = new int;\n i = new(i) int();}", + TranslationUnit::ParseTranlationUnit)); + QVERIFY(unit->ast()); + QCOMPARE(diag.errorCount, 0); +} + void tst_AST::initTestCase() { control.setDiagnosticClient(&diag); From 696129296ad3748a2eaade0f6f9ab0b77b8f1af8 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 5 Aug 2024 15:48:03 +0200 Subject: [PATCH 7/7] JsonWizard: Show error if some files fail to generate Do not overwrite error messages by an empty string, if the last file in the list successfully is determined. Also do not show the error message twice by avoiding the summarySettingsHaveChanged() call at the end of initialize(), which tries to contruct the generated file list again. Change-Id: Icaa329fcdd8882d49c4776aaced23e0094cfe857 Reviewed-by: Christian Stenger --- .../jsonwizard/jsonsummarypage.cpp | 7 +++++++ .../jsonwizard/jsonwizardfilegenerator.cpp | 16 ++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp index 8db6d46cac9..a5a6b7582a0 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp @@ -90,7 +90,14 @@ void JsonSummaryPage::initializePage() connect(m_wizard, &JsonWizard::filesReady, this, &JsonSummaryPage::triggerCommit); connect(m_wizard, &JsonWizard::filesReady, this, &JsonSummaryPage::addToProject); + // set result to accepted, so we can check if updateFileList -> m_wizard->generateFileList + // called reject() + m_wizard->setResult(QDialog::Accepted); updateFileList(); + // if there were errors while updating the file list, the dialog is rejected + // so don't continue the setup (which also avoids showing the error message again) + if (m_wizard->result() == QDialog::Rejected) + return; IWizardFactory::WizardKind kind = wizardKind(m_wizard); bool isProject = (kind == IWizardFactory::ProjectWizard); diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp index c6f6900d045..e48f93e9928 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp @@ -238,13 +238,17 @@ Core::GeneratedFiles JsonWizardFileGenerator::fileList(MacroExpander *expander, } const Core::GeneratedFiles result - = Utils::transform(fileList, - [this, &expander, &errorMessage](const File &f) { - return generateFile(f, expander, errorMessage); - }); + = Utils::transform(fileList, [this, &expander, &errorMessage](const File &f) { + QString generateError; + const Core::GeneratedFile file = generateFile(f, expander, &generateError); + if (!generateError.isEmpty()) + *errorMessage = generateError; + return file; + }); - if (Utils::contains(result, - [](const Core::GeneratedFile &gf) { return gf.filePath().isEmpty(); })) + if (Utils::contains(result, [](const Core::GeneratedFile &gf) { + return gf.filePath().isEmpty(); + })) return Core::GeneratedFiles(); return result;