Skip to content

Commit

Permalink
shiboken: Improve handling of pointer types for CONVERTTOCPP in injec…
Browse files Browse the repository at this point in the history
…ted code

Code snippets like:
QByteArray *cppSelf = %CONVERTTOCPP[QByteArray *](obj);

cause an assert in shiboken since the '*' is captured into
the target of the assignment and is not considered part of the type.

Make the error message a bit clearer and add documentation.

Fixes: PYSIDE-1037
Change-Id: Ie8da2f57ba91325ea677e1a00852e91726c0e09b
Reviewed-by: Christian Tismer <tismer@stackless.com>
  • Loading branch information
FriedemannKleint committed Jul 13, 2019
1 parent 035a299 commit f179662
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 4 deletions.
17 changes: 17 additions & 0 deletions sources/shiboken2/ApiExtractor/messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,23 @@ QString msgCannotUseEnumAsInt(const QString &name)
"Compilation errors may occur when used as a function argument.");
}

QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType)
{
QString result;
QTextStream str(&result);
str << "Types of receiver variable ('" << varType
<< "') and %%CONVERTTOCPP type system variable ('" << conversionType
<< "') differ";
QString strippedVarType = varType;
QString strippedConversionType = conversionType;
TypeInfo::stripQualifiers(&strippedVarType);
TypeInfo::stripQualifiers(&strippedConversionType);
if (strippedVarType == strippedConversionType)
str << " in qualifiers. Please make sure the type is a distinct token";
str << '.';
return result;
}

// main.cpp

QString msgLeftOverArguments(const QMap<QString, QString> &remainingArgs)
Expand Down
2 changes: 2 additions & 0 deletions sources/shiboken2/ApiExtractor/messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ QString msgCannotOpenForWriting(const QFile &f);

QString msgCannotUseEnumAsInt(const QString &name);

QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType);

QString msgLeftOverArguments(const QMap<QString, QString> &remainingArgs);

QString msgInvalidVersion(const QString &package, const QString &version);
Expand Down
23 changes: 23 additions & 0 deletions sources/shiboken2/doc/typesystemvariables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,29 @@ Variables
Replaced by a |project| conversion call that converts a Python variable
to a C++ variable of the type indicated by ``CPPTYPE``.

Typically, this is a variable assignment:

.. code-block:: c++

double value = %CONVERTTOCPP[double](pyValue);

Pointer assignments are also possible:

.. code-block:: c++

void f(double *valuePtr)
{
*valuePtr = %CONVERTTOCPP[double](pyValue);
Note however, that for variable definitions, the type must
be a space-delimited token:

.. code-block:: c++

double * valuePtr = %CONVERTTOCPP[double](pyValue);

since it otherwise would be indistinguishable from the pointer assignment
above.

.. _converttopython:

Expand Down
9 changes: 5 additions & 4 deletions sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ ShibokenGenerator::ShibokenGenerator()
const char CHECKTYPE_REGEX[] = R"(%CHECKTYPE\[([^\[]*)\]\()";
const char ISCONVERTIBLE_REGEX[] = R"(%ISCONVERTIBLE\[([^\[]*)\]\()";
const char CONVERTTOPYTHON_REGEX[] = R"(%CONVERTTOPYTHON\[([^\[]*)\]\()";
// Capture a '*' leading the variable name into the target
// so that "*valuePtr = %CONVERTTOCPP..." works as expected.
const char CONVERTTOCPP_REGEX[] =
R"((\*?%?[a-zA-Z_][\w\.]*(?:\[[^\[^<^>]+\])*)(?:\s+)=(?:\s+)%CONVERTTOCPP\[([^\[]*)\]\()";
m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegularExpression(QLatin1String(CHECKTYPE_REGEX));
Expand Down Expand Up @@ -2044,10 +2046,9 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
varType = miniNormalizer(varType);
QString varName = list.at(1).trimmed();
if (!varType.isEmpty()) {
if (varType != conversionType->cppSignature()) {
qFatal("Types of receiver variable ('%s') and %%CONVERTTOCPP type system variable ('%s') differ.",
qPrintable(varType), qPrintable(conversionType->cppSignature()));
}
const QString conversionSignature = conversionType->cppSignature();
if (varType != conversionSignature)
qFatal("%s", qPrintable(msgConversionTypesDiffer(varType, conversionSignature)));
c << getFullTypeName(conversionType) << ' ' << varName;
writeMinimalConstructorExpression(c, conversionType);
c << ';' << endl;
Expand Down

0 comments on commit f179662

Please sign in to comment.