aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlcompiler/qdeferredpointer_p.h
Commit message (Collapse)AuthorAgeFilesLines
* qmlcompiler: Avoid more QSharedPointer (con|de)structionFabian Kosmale2025-02-181-1/+1
| | | | | | Task-number: QTBUG-133349 Change-Id: Iafb2da52ea6230ead945f0eda978c53ca6a8e7c6 Reviewed-by: Sami Shalayel <[email protected]>
* qmlcompiler: Avoid pointless QSharedPointer (con|de)structionFabian Kosmale2025-02-031-2/+2
| | | | | | | | | The compiler can't optimize it away, and it's rather expensive to create and destroy a QSharedPointer on every usage of operator->. Task-number: QTBUG-133349 Change-Id: If1199a18b904ebce9921cc7b863792f407e45e0d Reviewed-by: Olivier De Cannière <[email protected]>
* QDeferredSharedPointer: don't populate eagerly on factory resetSami Shalayel2025-01-151-4/+2
| | | | | | | | | | | | | | | | Do not populate a pointer eagerly if it was already populated when its factory got reset. Instead reset the underlying shared pointer to delete the stale data. Amends 13761ee3c7d6ecb756db490d8c1fa8980117dca4 that wanted to avoid having stale data around. Add a test that reproduces the stack overflow when the pointer get eagerly populated, and make sure the stack size is big enough even for asan builds. Fixes: QTBUG-132134 Pick-to: 6.8 6.9 Change-Id: I8e2a5ce7fc99b1ec33d31535dc6b2675ab623349 Reviewed-by: Ulf Hermann <[email protected]>
* qmlls: implement commitToBase workflow for lazy filesSami Shalayel2024-05-231-0/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It seems that the current lazy QmlFile implementation does not take into account the commitToBase workflow used in qmlls, which leads to crashes and weird behaviors. Change the logic in QDeferredFactory<QQmlJSScope> to allow a custom TypeReader: QQmlJSTypeReader always reads from disk which is bad because qmlls operates most of the time on in-memory files and introduces an unnecessary IO operation, and therefore a new TypeReader is introduced in this commit for files loaded in the Dom. Populate lazy QmlFiles into the environment that they were loaded into with the new TypeReader before commitToBase() calls, and into the base environment after the commitToBase() call. This fixes the crashes during completion where a heap-use-after-free happened when a lazy file tried to populate itself after a commitToBase call using a destructed temporary DomEnvironment. Add a resetFactory() method to QDeferredSharedPtr to force recompute a QQmlJSScope when a file was changed without having to recreate all the qqmljsscopes for the other files, and use it also during commitToBase() calls to update the environment needed for the lazy loading. If the previous factory was used already, then the qqmljsscope is eagerly populated to avoid stale data. Also make sure to update the loadPaths for the build directory tests when getting a SemanticAnalysis struct from the base environment. Recreate the "completion crash" scenario from QTBUG-124799 in tst_qmldomitem. Add tests to make sure that files are correctly populated before and after commitToBase() calls. Also add a test in tst_qmlls_qqmlcodemodel to make sure that files are correctly lazy loaded in qqmlcodemodel, and simplify qqmlcompletionsupport's completions method by early exiting. Make populateFromQmlFile populate the logger in the same way as the QQmlJSTypeReader does. Fixes: QTBUG-124799 Fixes: QTBUG-125388 Change-Id: Id8bd7a1cbe60ba961eadb37b121f8f0670b863f4 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Ulf Hermann <[email protected]>
* Remove the use of Q_QMLCOMPILER_PRIVATE_EXPORTAlexey Edelev2024-01-091-1/+1
| | | | | | Task-number: QTBUG-117983 Change-Id: I893ba2a6c83af92d65d843b6a37bb14c6c1e45bf Reviewed-by: Ulf Hermann <[email protected]>
* QDeferred(Shared|Weak)Pointer: mark constructors [[nodiscard]]Marc Mutz2023-06-261-7/+7
| | | | | | | | | | | QDeferredSharedPointer and its weak companion are shared pointers, whose ctors QUIP-0019 asks to mark as [[nodiscard]]. QUIP: QUIP-0019 Task-number: QTBUG-104168 Pick-to: 6.6 Change-Id: Iba523f92276f4c77db21f8775629ae2c1b0dd43f Reviewed-by: Ulf Hermann <[email protected]>
* QDeferred(Shared|Weak)Pointer: mark certain operation [[nodiscard]]Marc Mutz2023-06-261-8/+8
| | | | | | | | | | | | | | Mark operations [[nodiscard]] which (directly or indirectly) execute lazyLoad(). Rationale: we should warn if deferred initialization is triggered without using the result. Intended uses can still use casting to void (and hopefully a comment) or [[maybe_unused]] to indicate the code works as intended. QUIP: QUIP-0019 Task-number: QTBUG-104168 Pick-to: 6.6 6.5 Change-Id: Iece9b36079c4af8d790b19703f81b284d507bf46 Reviewed-by: Ulf Hermann <[email protected]>
* Work around GCC 13 bogus warning about use-after-freeThiago Macieira2023-03-011-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | By simply adding std::move() to the variables we've received by value and aren't using again, thereby also improving performance slightly. The message was: In static member function ‘static void QSharedPointer<T>::deref(Data*) [with T = const QQmlJSScope]’, inlined from ‘void QSharedPointer<T>::deref() [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:440:12, inlined from ‘QSharedPointer<T>::~QSharedPointer() [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:280:30, inlined from ‘QDeferredSharedPointer<const QQmlJSScope>::~QDeferredSharedPointer()’ at qdeferredpointer_p.h:45:7, inlined from ‘QString QmltcCodeGenerator::generate_typeCount(Predicate, const InlineComponentOrDocumentRootName&) const cc1plus: error: pointer may be used after ‘void operator delete(void*)’ [-Werror=use-after-free] In static member function ‘static void QtSharedPointer::ExternalRefCountData::operator delete(void*)’, inlined from ‘static void QSharedPointer<T>::deref(Data*) [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:448:13, inlined from ‘static void QSharedPointer<T>::deref(Data*) [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:441:17, inlined from ‘void QSharedPointer<T>::deref() [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:440:12, inlined from ‘QSharedPointer<T>::~QSharedPointer() [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:280:30, inlined from ‘QDeferredSharedPointer<T>::operator QDeferredSharedPointer<const T>() const [with T = QQmlJSScope]’ at qdeferredpointer_p.h:75:83, inlined from ‘QString QmltcCodeGenerator::generate_typeCount(Predicate, const InlineComponentOrDocumentRootName&) const qsharedpointer_impl.h:130:67: note: call to ‘void operator delete(void*)’ here For reference: static void deref(Data *dd) noexcept { if (!dd) return; if (!dd->strongref.deref()) { dd->destroy(); } if (!dd->weakref.deref()) delete dd; } Note how there's one extra frame in the deletion sequence (QDeferredSharedPointer<T>::operator QDeferredSharedPointer<const T>()) compared to the use. The common source is if (t == visitor->result()) { // t is this document's root The variable `t` is a QDeferredSharedPointer<const QQmlJSScope>, but the right side is only QDeferredSharedPointer<QQmlJSScope>, which is why the conversion operator was called. operator QDeferredSharedPointer<const T>() const { return { m_data, m_factory }; } The above is calling the constructor QDeferredSharedPointer(QSharedPointer<T> data, QSharedPointer<Factory> factory) for T = const QQmlJSScope, which means it's calling template <class X, IfCompatible<X> = true> QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value), d(other.d) to construct the const version from m_data. This temporary is then moved into the QDeferredSharedPointer's argument because it's a prvalue by way of QSharedPointer's move constructor QSharedPointer(QSharedPointer &&other) noexcept : value(other.value), d(other.d) { other.d = nullptr; other.value = nullptr; } After the QDeferredSharedPointer's constructor returns, the temporary QSharedPointer is destroyed, which is where the compiler saw the call to operator delete. Except that it can't happen. The move constructor will have set the temporary's d pointer to null, so when deref() is called on that temporary, the check will match: if (!dd) return; Pick-to: 6.4 6.5 Change-Id: I7f354474adce419ca6c2fffd17482074d5cdc9d5 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Ulf Hermann <[email protected]> Reviewed-by: Marc Mutz <[email protected]>
* Use SPDX license identifiersLucie Gérard2022-06-111-27/+2
| | | | | | | | | | | | Replace the current license disclaimer in files by a SPDX-License-Identifier. Files that have to be modified by hand are modified. License files are organized under LICENSES directory. Pick-to: 6.4 Task-number: QTBUG-67283 Change-Id: I63563bbeb6f60f89d2c99660400dca7fab78a294 Reviewed-by: Shawn Rutledge <[email protected]>
* Avoid copying QQmlJSScopeUlf Hermann2022-04-041-7/+16
| | | | | | | | | | | | | | | | | | | | | | | | The factory should populate the pre-existing scope rather than copy it into place. This way we can detect inheritance cycles involving the pre-existing scope. However, now we may detect the inheritance cycles earlier, when resolving the types inside the lazy loading. We have the right pointers available there now, after all. Therefore, add a way to propagate base type errors out of the factory. When clearing the base type, we can now give a reason for that. When checking the inheritance cycles we retrieve that reason and log it. We also remove the special casing of the ScopeType property of QQmlJSScope. There is no real reason to set it in the ctor. As we delay the population of QQmlJSScope now, we have to set it later. Pick-to: 6.2 6.3 Task-number: QTBUG-102153 Change-Id: I49cf6e20f59fbdb6ed98a82040b3b159676f5975 Reviewed-by: Andrei Golubev <[email protected]> Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Don't export templatesUlf Hermann2022-04-021-2/+2
| | | | | Change-Id: I71a53492d046232109108f521e9223584b798e3c Reviewed-by: Maximilian Goldstein <[email protected]>
* QmlCompiler: Avoid excessive lazy loading in QDeferredWeakPointerUlf Hermann2022-04-011-7/+1
| | | | | | | We don't need to load the types just to compare the pointers. Change-Id: If93f7460f6e247f119f366a4c02a98d3e5f6535f Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Clean up exportsUlf Hermann2022-03-301-3/+3
| | | | | | | | We need to export all the classes used by qmlsc, and we need to use the private export macro for private symbols. Change-Id: I91d59611e864621dc2c49b9383596e706529bd42 Reviewed-by: Fabian Kosmale <[email protected]>
* Turn qmlcompiler into a shared libraryMaximilian Goldstein2022-03-251-2/+4
| | | | | | | | | Converts qmlcompiler into a shared library so it isn't duplicated when statically linked in tools and so that plugins can link against it. Change-Id: I91e13cc588796f71a5463dbdce21e42a74120565 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Qt CI Bot <[email protected]>
* Make sure all private headers include at least one otherThiago Macieira2022-03-101-1/+1
| | | | | | | | | | See script in qtbase/util/includeprivate for the rules. Since these files are being touched anyway, I also ran the updatecopyright.pl script too. Change-Id: Ib056b47dde3341ef9a52ffff13ef677e471674b6 Reviewed-by: Mitch Curtis <[email protected]>
* QQmlJSRegisterContent: Make conversions explicitUlf Hermann2022-02-151-0/+20
| | | | | | | | | | | | | Introduce a new kind to QQmlJSRegisterContent: "conversion". This is what we store when we merge multiple types together, or convert a selection of types into a new one. This way we can record what the original types were, and later figure out whether we can losslessly convert them already at the point where we store them. For now, only merges are implemented. Change-Id: If4ad0b1f075199e6aa1532959cf9591ba6755709 Reviewed-by: Fabian Kosmale <[email protected]>
* QDeferredSharedPointer: Don't needlessly lazyLoad and provide factoryUlf Hermann2021-12-121-9/+17
| | | | | | | | | | As we create the actual QSharedPointer and construction time, we can compare for equality or null without lazy loading. Furthermore, the factory, being a template parameter, can provide interesting additional functionality. Make it available in the public interface. Change-Id: Id1d4dd48d87c259dc93ee50e3b2d2510cdb54526 Reviewed-by: Fabian Kosmale <[email protected]>
* QDeferredSharedPointer: fix the build with GCC 12Giuseppe D'Angelo2021-10-091-0/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | Comparing via operator== a QDeferredSharedPointer with a QSharedPointer is ambiguous, as both convert to each other implictly, and there's only operator==(QDSP, QDSP) and operator==(QSP, QSP) defined. Therefore a "mixed" comparison is ambiguous: there's no dedicated operator==, and one can convert either parameter to the "other type" to get a viable candidate, and no conversion is better than the other. The result is: ../src/qmlcompiler/qqmljstyperesolver.cpp: In function ‘bool isAssignedToDefaultProperty(const ConstPtr&, const ConstPtr&)’: ../src/qmlcompiler/qqmljstyperesolver.cpp:565:29: error: ambiguous overload for ‘operator==’ (operand types are ‘QSharedPointer<const QQmlJSScope>’ and ‘const ConstPtr’ {aka ‘const QDeferredSharedPointer<const QQmlJSScope>’}) 565 | if (binding.value() == child) | ~~~~~~~~~~~~~~~ ^~ ~~~~~ | | | | | const ConstPtr {aka const QDeferredSharedPointer<const QQmlJSScope>} | QSharedPointer<const QQmlJSScope> Given that apparently implicit convertibility between QDSP and QSP is wanted, add mixed comparison operators to remove the ambiguity. Pick-to: 6.2 Change-Id: Ifcb1a2d86986d83c6f488097c9b4c8cb35db31d9 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* QDeferredWeakPointer: Remove data methodFabian Kosmale2021-10-011-2/+0
| | | | | | | | | | | It calls QWeakPointer::data, which shouldn't actually exist and is not actually used anywhere. The safe way to access the data of a weak pointer is to create a shared pointer from it, which ensures that there is a strong reference to the data while we are accessing it. Change-Id: I89ddfb85735d2ee56a8a882373ffc0444b564b13 Reviewed-by: Ulf Hermann <[email protected]>
* Remove qHash for QDeferredWeakPointerFabian Kosmale2021-10-011-6/+0
| | | | | | | | Weak pointers shouldn't be used as keys of a hash map, and in fact are not used as such in declarative. Change-Id: Ib84b9a090683332ae2c57e59506caae1aac62a48 Reviewed-by: Ulf Hermann <[email protected]>
* QDeferredSharedPointer: Do not use factory after lazy loadingUlf Hermann2021-09-231-4/+4
| | | | | | | | | | Otherwise a lazy loaded deferred pointer is different from an immediately loaded deferred pointer of the same object. Pick-to: 6.2 Change-Id: I235907f82f10d2af5002ae6c3a852f3235dd802c Reviewed-by: Andrei Golubev <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* Add QDeferredSharedPointer::get()Andrei Golubev2021-03-301-0/+1
| | | | | | | Because QSharedPointer (and almost any other smart pointer) provides it Change-Id: I7e0cf0d700ed72de56b6949ee18b3469881088b3 Reviewed-by: Fabian Kosmale <[email protected]>
* QDeferredSharedPointer: lazy-load to determine isNull()Ulf Hermann2021-01-261-16/+42
| | | | | | | | | | | If the content is not loaded, yet, the data is always null. If it is loaded, the result might be null. So, in order to know, we have to load. The same holds for deferred weak pointers, the hash functions, and the equality operators. Change-Id: I20eec58efe5da604187c34578ee40f769090c910 Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Use size_t for qHashUlf Hermann2020-10-221-2/+2
| | | | | | | | It is expected to return an unsigned value. Change-Id: Id75c0887de7e9b0eeab378041598621c89507501 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Maximilian Goldstein <[email protected]>
* QmlCompiler: add operator!= to QDeferredPointerUlf Hermann2020-10-151-0/+10
| | | | | Change-Id: I2191660b731d85495d0e90152e0fe493553b7a2f Reviewed-by: Fabian Kosmale <[email protected]>
* QDeferredPointer: Remove the factory before executing itUlf Hermann2020-10-151-5/+7
| | | | | | | Only this way we avoid infinite recursion on cyclic references. Change-Id: I4d6323a093d17f7d55965dc40f9dc5f1a647df9c Reviewed-by: Fabian Kosmale <[email protected]>
* qmllint: Defer resolution of types read from QML filesUlf Hermann2020-10-151-0/+181
When importing a directory we most likely don't need all of the files in the directory. Therefore we now parse them only when they are accessed. This speeds up the execution and will allow us to process imports recursively without running into infinite recursion. Change-Id: I0c79313de792249e6bb86144b5014a7787dbdc5b Reviewed-by: Fabian Kosmale <[email protected]>