Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmljsshadowcheck.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
5
7
8using namespace Qt::StringLiterals;
9
38 InstructionAnnotations *annotations, const Function *function,
40{
41 m_annotations = annotations;
43 m_error = error;
44 m_state = initialState(function);
45 decode(m_function->code.constData(), static_cast<uint>(m_function->code.size()));
46}
47
49{
50 if (!m_state.readsRegister(Accumulator))
51 return; // enum lookup cannot be shadowed.
52
53 auto accumulatorIn = m_state.registers.find(Accumulator);
54 if (accumulatorIn != m_state.registers.end()) {
55 checkShadowing(
56 accumulatorIn.value().content, m_jsUnitGenerator->stringForIndex(nameIndex),
58 }
59}
60
62{
63 if (!m_state.readsRegister(Accumulator))
64 return; // enum lookup cannot be shadowed.
65
66 auto accumulatorIn = m_state.registers.find(Accumulator);
67 if (accumulatorIn != m_state.registers.end()) {
68 checkShadowing(
69 accumulatorIn.value().content, m_jsUnitGenerator->lookupName(index), Accumulator);
70 }
71}
72
74{
75 checkShadowing(
76 m_state.registers[base].content, m_jsUnitGenerator->stringForIndex(nameIndex), base);
77}
78
80{
81 checkShadowing(m_state.registers[base].content, m_jsUnitGenerator->lookupName(index), base);
82}
83
84void QQmlJSShadowCheck::generate_CallProperty(int nameIndex, int base, int argc, int argv)
85{
86 Q_UNUSED(argc);
87 Q_UNUSED(argv);
88 checkShadowing(m_state.registers[base].content, m_jsUnitGenerator->lookupName(nameIndex), base);
89}
90
91void QQmlJSShadowCheck::generate_CallPropertyLookup(int nameIndex, int base, int argc, int argv)
92{
93 Q_UNUSED(argc);
94 Q_UNUSED(argv);
95 checkShadowing(m_state.registers[base].content, m_jsUnitGenerator->lookupName(nameIndex), base);
96}
97
99{
100 m_state = nextStateFromAnnotations(m_state, *m_annotations);
101 return (m_state.hasSideEffects() || m_state.changedRegisterIndex() != InvalidRegister)
104}
105
107{
108}
109
110void QQmlJSShadowCheck::checkShadowing(
111 const QQmlJSRegisterContent &baseType, const QString &memberName, int baseRegister)
112{
113 if (baseType.storedType()->accessSemantics() != QQmlJSScope::AccessSemantics::Reference)
114 return;
115
116 switch (baseType.variant()) {
121 const QQmlJSRegisterContent member = m_typeResolver->memberType(baseType, memberName);
122
123 // You can have something like parent.QtQuick.Screen.pixelDensity
124 // In that case "QtQuick" cannot be resolved as member type and we would later have to look
125 // for "QtQuick.Screen" instead. However, you can only do that with attached properties and
126 // those are not shadowable.
127 if (!member.isValid()) {
128 Q_ASSERT(m_typeResolver->isPrefix(memberName));
129 return;
130 }
131
132 if (member.isProperty()) {
133 if (member.property().isFinal())
134 return; // final properties can't be shadowed
135 } else if (!member.isMethod()) {
136 return; // Only properties and methods can be shadowed
137 }
138
139 m_logger->log(
140 u"Member %1 of %2 can be shadowed"_s.arg(
141 memberName, m_state.accumulatorIn().descriptiveName()),
143
144 // Make it "var". We don't know what it is.
146 const QQmlJSRegisterContent varContent = m_typeResolver->globalType(varType);
147 InstructionAnnotation &currentAnnotation = (*m_annotations)[currentInstructionOffset()];
148
149 if (currentAnnotation.changedRegisterIndex != InvalidRegister) {
151 currentAnnotation.changedRegister.storedType(), varType);
153 m_typeResolver->containedType(currentAnnotation.changedRegister), varType);
154 }
155
156 for (auto it = currentAnnotation.readRegisters.begin(),
157 end = currentAnnotation.readRegisters.end();
158 it != end; ++it) {
159 if (it.key() != baseRegister)
160 it->second.content = m_typeResolver->convert(it->second.content, varContent);
161 }
162
163 return;
164 }
165 default:
166 // In particular ObjectById is fine as that cannot change into something else
167 // Singleton should also be fine, unless the factory function creates an object
168 // with different property types than the declared class.
169 return;
170 }
171}
172
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
iterator end()
Definition qflatmap_p.h:773
iterator find(const Key &key)
Definition qflatmap_p.h:816
const QV4::Compiler::JSUnitGenerator * m_jsUnitGenerator
const Function * m_function
const QQmlJSTypeResolver * m_typeResolver
QQmlJS::DiagnosticMessage * m_error
State initialState(const Function *function)
State nextStateFromAnnotations(const State &oldState, const InstructionAnnotations &annotations)
QQmlJS::SourceLocation currentSourceLocation() const
void log(const QString &message, QQmlJS::LoggerWarningId id, const QQmlJS::SourceLocation &srcLocation, bool showContext=true, bool showFileName=true, const std::optional< QQmlJSFixSuggestion > &suggestion={}, const QString overrideFileName=QString())
QQmlJSMetaProperty property() const
ContentVariant variant() const
QQmlJSScope::ConstPtr storedType() const
AccessSemantics accessSemantics() const
void endInstruction(QV4::Moth::Instr::Type) override
void generate_CallPropertyLookup(int nameIndex, int base, int argc, int argv) override
QV4::Moth::ByteCodeHandler::Verdict startInstruction(QV4::Moth::Instr::Type) override
void generate_SetLookup(int index, int base) override
void generate_LoadProperty(int nameIndex) override
void generate_CallProperty(int nameIndex, int base, int argc, int argv) override
void generate_GetLookup(int index) override
void generate_StoreProperty(int nameIndex, int base) override
void run(InstructionAnnotations *annotations, const Function *function, QQmlJS::DiagnosticMessage *error)
QQmlJSRegisterContent memberType(const QQmlJSRegisterContent &type, const QString &name) const
QQmlJSScope::ConstPtr containedType(const QQmlJSRegisterContent &container) const
bool isPrefix(const QString &name) const
QQmlJSRegisterContent globalType(const QQmlJSScope::ConstPtr &type) const
QQmlJSRegisterContent convert(const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const
void adjustOriginalType(const QQmlJSScope::ConstPtr &tracked, const QQmlJSScope::ConstPtr &conversion) const
QQmlJSScope::ConstPtr varType() const
iterator begin()
Definition qset.h:136
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QSet< QString >::iterator it
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError * error
GLuint index
[2]
GLuint GLuint end
const QQmlJS::LoggerWarningId qmlCompiler
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:29
#define decode(x)
const QQmlJSRegisterContent & accumulatorIn() const
bool readsRegister(int registerIndex) const
QString lookupName(int index) const
QString stringForIndex(int index) const