aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlcompiler/qqmljsregistercontent.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Add security header for src/qmlcompilerOlivier De Cannière2025-09-171-0/+1
| | | | | | | | | | | | | | | | | | We assume that QML or JS code comes from a trusted source. Therefore, most files are deemed to be significant even if they parse data. This includes the source code itself but also the associated metadata or cache files. However, the QML compiler also generates C++ code. Extra care needs to be taken with the generator as a vulnerability there could propagate and have a disproportionate effect on the program's security. It is marked as critical. QUIP: 23 Fixes: QTBUG-136195 Pick-to: 6.10 6.9 6.8 Change-Id: I70630361ec8e9cb3969f78a3fdf36a41334a33b3 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Compiler: Include updated type in property registers' descriptive nameOlivier De Cannière2025-04-171-1/+9
| | | | | | | | | The typeName may be incorrect if the property's type is later adjusted. Task-number: QTBUG-134790 Pick-to: 6.9 6.8 Change-Id: I58c95e873a1d1eb0a2c9d0d0c7b34664d75eadff Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QmlCompiler: Periodically trim register content poolUlf Hermann2024-12-031-0/+11
| | | | | | | | | | | | | The code generator uses temporary register contents for various purposes. None of those survive across instructions since there wouldn't be anywhere to store them. We don't need to keep those temporaries around until the end of the compilation. Trim them after each instruction. Task-number: QTBUG-124670 Change-Id: Ia6ff7ff2a9c7a5e99ab37ab2cc3e5f7ee756b57c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Store QQmlJSRegisterContent in place where we canUlf Hermann2024-12-031-0/+11
| | | | | | | | | | There is no need anymore to create a new QQmlJSRegisterContentPrivate just to add a storage type. Furthermore, we should record the generalization origin when generalizing storage. Task-number: QTBUG-124670 Change-Id: Ib1413e645fbc927806f85c7aa235c95a4cbfaa96 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Pass QQmlJSRegisterContent by valueUlf Hermann2024-12-031-13/+13
| | | | | | | | | It's only a single pointer these days. Task-number: QTBUG-124670 Change-Id: Id51fe268108733b07d77c70531f38914a8adfdae Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Improve naming of QQmlRegisterContentPool methodsUlf Hermann2024-12-031-8/+8
| | | | | | | The name should say what kind of QQmlJSRegisterContent it creates. Change-Id: Ia77bfc7c2a34395ca9e54ba496acd9d6883152cb Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Clean up API of QQmlJSRegisterContentUlf Hermann2024-12-031-9/+14
| | | | | | | | Rename some methods and write some comments. Task-number: QTBUG-124670 Change-Id: I3046d545374c92dd7441d58d2b8fe2abc25078b8 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Move type adjustment into QQmlJSRegisterContentUlf Hermann2024-11-281-0/+70
| | | | | | | | | | | | | | | | | | | | | | | | | | This is the central piece of the refactoring. Instead of re-writing the QQmlJSScopes on adjustment we now rewrite the QQmlJSRegisterContents. The main benefit of this is that we can locally link QQmlJSRegisterContents together without invoking QQmlJSTypeResolver. The other benefit is that we gain more control over where the re-written types show up. QQmlJSScope is stored in many places that should really not be re-written. QQmlJSRegisterContent is only used locally when analyzing a binding or function. Finally, we can now chain the type adjustments with other operations on QQmlJSRegisterContents, without restrictions. This makes a few methods of QQmlJSTypeResolver obsolete. Those will be removed in a separate step. In order to get this right, we need to deviate from the notion that every read register is either a rename or a conversion. Rather, we must pass any "as-is" read of a register through that way. We rely on those to be re-written when the original register is. Task-number: QTBUG-124670 Change-Id: I0d968dfe495b82d9d9f67d598447bd2ad5bdcd04 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Make QQmlJSRegisterContentPrivate non-constUlf Hermann2024-11-251-19/+37
| | | | | | | | | | | | | | | | | This is a major departure from the previous architecture. We can now alter a QQmlJSRegisterContentPrivate after it has been created. This is fundamentally necessary so that we can add further links to other types as they are discovered. With an immutable QQmlJSRegisterContentPrivate we have to clone every time which makes for long and rather meaningless chains of links that are hard to navigate, eventually. Making the register content non-const will in turn allow us to uphold the immutability of QQmlJSScope. That is much more important because it can fundamentally be used across different compilations. Task-number: QTBUG-124670 Change-Id: Iacee705be3260da0a2bc91c6758f91c70a137065 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Phrase as-cast as an explicit operationUlf Hermann2024-11-221-1/+1
| | | | | | | | | The other transformations that previously used castTo() are better phrased as conversions rather than casts. Task-number: QTBUG-124670 Change-Id: I3cf885edcac6fa665a6ad12b97f6d063709a1632 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Phrase register content storage as register contentUlf Hermann2024-11-211-14/+17
| | | | | | | | We will need to link the storage to its adjustment eventually. Task-number: QTBUG-124670 Change-Id: I50db4f7af34cc2f41f9a43e5fe271ecdf75fe655 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Split QQmlJSRegisterContent in public and private classesUlf Hermann2024-11-201-52/+375
| | | | | | | | | | | | | | | | | | | | | | | | | We want an easy way to hold pointers to other QQmlJSRegisterContents in QQmlJSRegisterContent. Furthermore, copying a QQmlJSRegisterContent so far is very expensive. Solve both problems by introducing the PIMPL pattern with a shared d-pointer. This also changes the equality semantics of QQmlJSRegisterContent. Two QQmlJSRegisterContents are only equal if they contain the same d-pointer now, not if their contents are otherwise equal. However, since we generally don't rely on immediate equality of QQmlJSRegisterContent anyway, this is not a problem. QQmlJSTypeResolver::equals() still works. There is one place where the equality was used, though. That one is adapted. Furthermore, we now want to keep the register contents in a pool that's automatically cleared when we're done with our analysis. Therefore the creation methods cannot be static anymore and storedIn() as well as castTo() need to go through the pool as well. Task-number: QTBUG-124670 Change-Id: I0a51b609fc769ccb33c1d82930bda83c2a40e1a5 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Make the ScopeObject content variant more usefulUlf Hermann2024-10-241-21/+0
| | | | | | | | | We can use it for JavaScript local and global scopes, too. To this end, check for the actual QML scope object where we want that one. Task-number: QTBUG-124670 Change-Id: I908a4f122a83d6685129cb24959353a1169faae0 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Unify the method call content variantsUlf Hermann2024-10-131-2/+26
| | | | | | | | | | | We can infer from the method itself whether it's a JavaScript call or a C++ call. Therefore, what we need to carry around is the QQmlJSMetaMethod. This way we can do with only one content variant for all kinds of calls. Task-number: QTBUG-124670 Change-Id: I1d8193018f0224924b8aef5181c398674bde857d Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Simplify content variants for QQmlJSRegisterContentUlf Hermann2024-10-121-0/+46
| | | | | | | | | | | Instead of having a cross product of "scope" and "object" on the one hand and "property", "method" and "enum" on the other hand, use the scopeType to resolve what kind of element a property, method or enum belongs to. Task-number: QTBUG-124670 Change-Id: Ia9db05e13979e55e0ed7912afc2003dfd018987a Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Store full type information for conversion originsUlf Hermann2024-10-101-6/+1
| | | | | | | | | | With this in place, we don't have to synthesize conversion origins anymore and get to trace values through conversions. Task-number: QTBUG-124670 Change-Id: Ib3646d410526eca7b982f86adef9d5a387ff56ea Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Require QQmlJSRegisterContent as scope typesUlf Hermann2024-10-081-14/+32
| | | | | | | | | | | | | | | | | This is the first step in chaining up the values in a graph. We can only derive the next node of the graph if we have a full previous node. QQmlJSRegisterContent will ultimately just be a container for a node. Prepare for this by requiring QQmlJSRegisterContent as input when creating a new register content. In some cases we can't actually nest contents, yet. Therefore we chicken out by creating synthetic QQmlJSRegisterContents. Task-number: QTBUG-124670 Change-Id: Idad793692ca78d71ba17107d396e508bc1392b67 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QmlCompiler: Make QQmlJSRegisterContent::ContentKind a scoped enumUlf Hermann2024-06-201-13/+13
| | | | | | | | | The syntax is slightly annoying, but we want the generic names like Property and Method for the public ContentVariant enum. Change-Id: Ifb70340bb5143854a88ff3de78bcb585f49872f1 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Always report attached type name as name of an attachmentUlf Hermann2024-06-201-2/+0
| | | | | | | | | There is no point in reporting the C++ name of the type, but then not going all the way and reporting the type we actually mean. Change-Id: I9d12d34ab65766f7a396c70ddae2bbe573fa7778 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QmlCompiler: Move containedTypeName() into QQmlJSRegisterContentUlf Hermann2024-06-161-0/+19
| | | | | | | | | We don't need the type resolver for that. And since we always want the "fancy" name, drop the extra argument. Change-Id: I14278b5a297fc0e8101f03e5098a831a91deaf9e Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Create QQmlJSRegisterContent unstoredUlf Hermann2024-06-161-52/+28
| | | | | | | | | | Add a separate pass to populate the stored types and only run that after we're done with all the type propagation and optimization. Task-number: QTBUG-124670 Change-Id: I740063908b22684f5d2c72d6261fad98850d8636 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Reduce the usage of storedType()Ulf Hermann2024-06-161-16/+54
| | | | | | | | | | | | We don't actually need the stored type until we hit the storage generalizer. There are two cases where the stored type is the same as the contained type: methods and import namespaces. Store the contained type separately in those cases. Task-number: QTBUG-124670 Change-Id: I395203ab204162b2754914438f56546e07453272 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qmlcachegen: Improve warnings for missing return type annotationsOlivier De Cannière2024-04-231-11/+20
| | | | | | | Fixes: QTBUG-124220 Pick-to: 6.7 Change-Id: Ic31b90b0408d855a45e17647ab659fbbc6e17633 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Retrieve original types for comparisonUlf Hermann2023-11-131-1/+1
| | | | | | | | | | | | If an original type is merely wrapped into a more generic type by the basic blocks pass, we know the original data is still there and can be used for comparison. Fixes: QTBUG-117795 Change-Id: Ia7582cd8ed48e47a3a1b3bd8e2595e9cb42828de Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Store lookupIndex in register content for propertiesUlf Hermann2023-08-241-7/+10
| | | | | | | | | This way we can generate a separate register variable for the result of each lookup, which guarantees that we can write back to it if necessary. Task-number: QTBUG-116011 Change-Id: I1d2b8948d8edb66f0665399768df194065dc99be Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Fix SetLookup on shadowable propertiesUlf Hermann2023-08-081-1/+2
| | | | | | | | | | | | | | | | | | | | | If we are procedurally setting a shadowable property, the read register for the value will be converted to var. We can therefore not just retrieve the property type again in the code generator to determine what we have to do. What we actually need is the information on the original scope type of the lookup. We need to know what exactly the base type was supposed to be. To that effect, store the scope of the target for each conversion in QQmlJSRegisterContent. We need to circumvent the questionable optimization of "deduplicating" functions that certain compilers exhibit, like we do for the getters. Pick-to: 6.6 Fixes: QTBUG-115526 Change-Id: I361f2e46e39ece7892df72ae13ec756f9aec4adf Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Allow lists as arguments to methodsUlf Hermann2022-11-101-5/+3
| | | | | | | | | | | | | | | | | | | Since lists are allowed as property types, you should be able to pass them as arguments to methods, too. For now we only handle QML-defined methods, implemented by adding JavaScript functions to your QML elements. The usual type coercion rules apply if you pass JavaScript arrays to such methods. That is, it usually works. We now resolve properties with the "list" flag to their actual types (QQmlListProperty or QList) already when populating the QQmlJSScope, and store the list types as members of QQmlJSScope rather than as a special map in QQmlJSTypeResolver. This allows us to do the same to lists passed as arguments and simplifies some of the type analysis. Fixes: QTBUG-107171 Change-Id: Idf71ccdc1d59f472c17084a36b5d7879c4d959c0 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Port to new Q_UNREACHABLE_RETURN()Marc Mutz2022-10-201-2/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a semantic patch using ClangTidyTransformator to convert sequences of Q_UNREACHABLE() + return into Q_UNREACHABLE_RETURN(), newly added to qtbase. const std::string unr = "unr", val = "val", ret = "ret"; auto makeUnreachableReturn = cat("Q_UNREACHABLE_RETURN(", ifBound(val, cat(node(val)), cat("")), ")"); auto ignoringSwitchCases = [](auto stmt) { return anyOf(stmt, switchCase(subStmt(stmt))); }; makeRule(stmt(ignoringSwitchCases(stmt(isExpandedFromMacro("Q_UNREACHABLE")).bind(unr)), nextStmt(returnStmt(optionally(hasReturnValue(expr().bind(val)))).bind(ret))), {changeTo(node(unr), cat(makeUnreachableReturn, ";")), // TODO: why is the ; lost w/o this? changeTo(node(ret), cat(""))}, cat("use ", makeUnreachableReturn)); a.k.a qt-use-unreachable-return. subStmt() and nextStmt() are non-standard matchers. There was one false positive, suppressed it with NOLINTNEXTLINE. It's not really a false positiive, it's just that Clang sees the world in one way and if conditonal compilation (#if) differs for other compilers, Clang doesn't know better. This is an artifact of matching two consecutive statements. Change-Id: I3855b2dc8523db1ea860f72ad9818738162495c6 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* 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 <shawn.rutledge@qt.io>
* Replace uses of deprecated _qs with _s/QStringLiteralSona Kurazyan2022-04-291-13/+15
| | | | | | Task-number: QTBUG-101408 Change-Id: Ic925751b73f52d8fa5add5cacc52d6dd6ea2dc27 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QmlCompiler: Allow retrieval of descriptive name from invalid typesUlf Hermann2022-04-071-0/+5
| | | | | | | | | Apparently we do that somewhere. It should not just crash. Pick-to: 6.2 6.3 Task-number: QTBUG-102147 Change-Id: Id612e0543d8794aa4f334a899b117142b7a8cd38 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Clean up exportsUlf Hermann2022-03-301-6/+0
| | | | | | | | 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 <fabian.kosmale@qt.io>
* qmlcompiler: Store filename for QML scopesMaximilian Goldstein2022-02-251-2/+2
| | | | | | | | | | | Previously the filename was only available for C++ types that have been exposed via qmltypes. Now every scope has a valid filename to reference. This is important in order to give more useful hints to the user and will also prove useful for debugging. Change-Id: I6142b58278f388814514fffd86cbc241eb969bb2 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QQmlJSRegisterContent: Make conversions explicitUlf Hermann2022-02-151-0/+18
| | | | | | | | | | | | | 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 <fabian.kosmale@qt.io>
* qmlcompiler: Add a content variant for module prefixesUlf Hermann2021-08-191-0/+13
| | | | | | | | | | | The code generator needs to see the modulePrefix as a separate step in order to generate sensible code. The savedPrefix we had before was not exposed to the code generator. As an added benefit we can also check that we don't refer to singletons as properties of objects this way. Task-number: QTBUG-95822 Change-Id: Ia8992dba340bf0552e7647f0d66b441f1ac1b8c8 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qmlcompiler: Port type inference code from qmlcachegenplusMaximilian Goldstein2021-06-301-0/+149
Move the type inference code so qmllint can benefit from the improved type analysis. Change-Id: I00b2fad8334ec19fb33a45b3ceec9d6c49d12e93 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>