genbindings: preserve const/ptr attributes through typedefs

This commit is contained in:
mappu 2024-09-18 13:08:18 +12:00
parent db09326a76
commit eae85ac325
8 changed files with 91 additions and 91 deletions

View File

@ -84,11 +84,19 @@ func (p CppParameter) RenderTypeCabi() string {
ret += "*"
}
return ret // ignore const
return ret
}
// RenderTypeQtCpp renders the Qt C++ type in the original form from the function
// definition, before any typedefs or transformations were applied.
func (p CppParameter) RenderTypeQtCpp() string {
cppType := p.GetQtCppType()
return p.GetQtCppType().RenderTypeIntermediateCpp()
}
// RenderTypeIntermediateCpp renders the Qt C++ type WITHOUT resolving the
// interior QtCppOriginalType. This is used for intermediate const_cast<>s.
func (p CppParameter) RenderTypeIntermediateCpp() string {
cppType := p.ParameterType
if p.Const {
cppType = "const " + cppType
@ -178,9 +186,13 @@ func emitParametersCABI2CppForwarding(params []CppParameter, indent string) (pre
return preamble, strings.Join(tmp, ", ")
}
func makeNamePrefix(in string) string {
return strings.Replace(strings.Replace(in, `[`, `_`, -1), `]`, "", -1)
}
func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, forwarding string) {
nameprefix := strings.Replace(strings.Replace(p.ParameterName, `[`, `_`, -1), `]`, "", -1)
nameprefix := makeNamePrefix(p.ParameterName)
if p.ParameterType == "QString" {
// The CABI has accepted two parameters - need to convert to one real QString
@ -204,17 +216,7 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
preamble += indent + "}\n"
return preamble, nameprefix + "_QList"
} else if p.IsKnownEnum() {
// The enums are projected in CABI as their underlying int types.
// Cast to the Qt enum type so that we get the correct overload
return preamble, "static_cast<" + p.RenderTypeQtCpp() + ">(" + p.ParameterName + ")"
} else if p.IsFlagType() {
return preamble, "static_cast<" + p.RenderTypeQtCpp() + ">(" + p.ParameterName + ")"
} else if p.IntType() {
// Use the raw ParameterType to select an explicit integer overload
// Don't use RenderTypeCabi() since it canonicalizes some int types for CABI
} else if p.IntType() || p.IsFlagType() || p.IsKnownEnum() {
castSrc := p.ParameterName
castType := p.RenderTypeQtCpp()
@ -222,6 +224,10 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
castSrc = "*" + castSrc
}
if p.QtCppOriginalType != nil && p.QtCppOriginalType.Const != p.Const {
return preamble, "static_cast<" + p.RenderTypeQtCpp() + ">(const_cast<" + p.RenderTypeIntermediateCpp() + ">(" + p.ParameterName + "))"
}
if p.ParameterType == "qint64" ||
p.ParameterType == "quint64" ||
p.ParameterType == "qlonglong" ||
@ -283,7 +289,7 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
shouldReturn = shouldReturn[len(indent):]
namePrefix := p.ParameterName // TODO make unique, strip out [0], etc
namePrefix := makeNamePrefix(p.ParameterName)
if p.ParameterType == "void" && !p.Pointer {
shouldReturn = ""
@ -366,15 +372,15 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
// Elide temporary and emit directly from the rvalue
return indent + assignExpression + "new " + p.ParameterType + "(" + rvalue + ");\n"
} else if p.IsFlagType() {
// Needs an explicit int cast
} else if p.IsFlagType() || p.IsKnownEnum() || p.QtCppOriginalType != nil {
// Needs an explicit cast
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
afterCall += indent + "" + assignExpression + "static_cast<int>(" + namePrefix + "_ret);\n"
} else if p.IsKnownEnum() || p.QtCppOriginalType != "" {
// Needs an explicit uintptr cast
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
afterCall += indent + "" + assignExpression + "static_cast<" + p.RenderTypeCabi() + ">(" + namePrefix + "_ret);\n"
if p.QtCppOriginalType != nil && p.QtCppOriginalType.Const != p.Const {
afterCall += indent + "" + assignExpression + "const_cast<" + p.RenderTypeCabi() + ">(static_cast<" + p.RenderTypeIntermediateCpp() + ">(" + namePrefix + "_ret));\n"
} else {
afterCall += indent + "" + assignExpression + "static_cast<" + p.RenderTypeCabi() + ">(" + namePrefix + "_ret);\n"
}
} else if p.Const {
shouldReturn += "(" + p.RenderTypeCabi() + ") "

View File

@ -214,7 +214,7 @@ func (gfs *goFileState) emitParametersGo2CABIForwarding(m CppMethod) (preamble s
func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble string, rvalue string) {
nameprefix := strings.Replace(strings.Replace(p.ParameterName, `[`, `_`, -1), `]`, "", -1)
nameprefix := makeNamePrefix(p.ParameterName)
if p.ParameterType == "QString" {
// Go: convert string -> miqt_string*
@ -285,7 +285,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
shouldReturn := "return "
afterword := ""
namePrefix := rt.ParameterName
namePrefix := makeNamePrefix(rt.ParameterName)
if rt.ParameterType == "void" && !rt.Pointer {
shouldReturn = ""
@ -370,7 +370,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
}
}
} else if rt.IntType() || rt.IsKnownEnum() || rt.IsFlagType() || rt.ParameterType == "bool" || rt.QtCppOriginalType != "" {
} else if rt.IntType() || rt.IsKnownEnum() || rt.IsFlagType() || rt.ParameterType == "bool" || rt.QtCppOriginalType != nil {
// Need to cast Cgo type to Go int type
// Optimize assignment to avoid temporary
return assignExpr + "(" + rt.RenderTypeGo() + ")(" + rvalue + ")\n"

View File

@ -133,16 +133,13 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
// std::seed_seq QRandom
return ErrTooComplex
}
if strings.Contains(p.ParameterType, `::reverse_iterator`) || strings.Contains(p.ParameterType, `::const_reverse_iterator`) {
return ErrTooComplex // e.g. qbytearray.h
}
if strings.Contains(p.ParameterType, `Iterator::value_type`) {
return ErrTooComplex // e.g. qcbormap
}
if strings.Contains(p.ParameterType, `::QPrivate`) {
return ErrTooComplex // e.g. QAbstractItemModel::QPrivateSignal
}
if strings.Contains(p.GetQtCppType(), `::DataPtr`) {
if strings.Contains(p.GetQtCppType().ParameterType, `::DataPtr`) {
return ErrTooComplex // e.g. QImage::data_ptr()
}
@ -191,9 +188,6 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
"char16_t", // e.g. QChar() constructor overload, just unnecessary
"char32_t", // e.g. QDebug().operator<< overload, unnecessary
"wchar_t", // e.g. qstringview.h overloads, unnecessary
"QStringView::const_pointer", // e.g. qstringview.h data()
"QStringView::const_iterator", // e.g. qstringview.h
"QStringView::value_type", // e.g. qstringview.h
"FILE", // e.g. qfile.h constructors
"qInternalCallback", // e.g. qnamespace.h
"QGraphicsEffectSource", // e.g. used by qgraphicseffect.h, but the definition is in ????
@ -233,11 +227,11 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
// generated headers (generated on Linux) with other OSes such as Windows.
// These methods will be blocked on non-Linux OSes.
func LinuxWindowsCompatCheck(p CppParameter) bool {
if p.GetQtCppType() == "Q_PID" {
if p.GetQtCppType().ParameterType == "Q_PID" {
return true // int64 on Linux, _PROCESS_INFORMATION* on Windows
}
if p.GetQtCppType() == "QSocketDescriptor::DescriptorType" {
if p.GetQtCppType().ParameterType == "QSocketDescriptor::DescriptorType" {
return true // uintptr_t-compatible on Linux, void* on Windows
}
return false

View File

@ -37,25 +37,23 @@ func init() {
}
type CppParameter struct {
ParameterName string
ParameterType string
QtCppOriginalType string // If we rewrote QStringList->QList<String>, this field contains the original QStringList. Otherwise, it's blank
Const bool
Pointer bool
PointerCount int
ByRef bool
Optional bool
}
ParameterName string
ParameterType string
Const bool
Pointer bool
PointerCount int
ByRef bool
Optional bool
func (p *CppParameter) AssignAlias(newType string) {
if p.QtCppOriginalType == "" {
p.QtCppOriginalType = p.ParameterType // Overwrite once only, at the earliest base type
}
p.ParameterType = newType
QtCppOriginalType *CppParameter // If we rewrote QStringList->QList<String>, this field contains the original QStringList. Otherwise, it's blank
}
func (p *CppParameter) ApplyTypedef(matchedUnderlyingType CppParameter) {
p.AssignAlias(matchedUnderlyingType.ParameterType)
if p.QtCppOriginalType == nil {
tmp := *p // Copy
p.QtCppOriginalType = &tmp // Overwrite once only, at the earliest base type
}
p.ParameterType = matchedUnderlyingType.ParameterType
// If this was a pointer to a typedef'd type, or a typedef of a pointer type, we need to preserve that
p.Const = p.Const || matchedUnderlyingType.Const
@ -78,20 +76,17 @@ func (p *CppParameter) ConstCast(isConst bool) CppParameter {
return ret
}
func (p *CppParameter) GetQtCppType() string {
if p.QtCppOriginalType != "" {
func (p *CppParameter) GetQtCppType() *CppParameter {
if p.QtCppOriginalType != nil {
return p.QtCppOriginalType
}
return p.ParameterType
return p
}
func (p CppParameter) IsFlagType() bool {
if strings.HasPrefix(p.ParameterType, `QFlags<`) {
return true // This catches most cases through the typedef system
}
if strings.HasPrefix(p.GetQtCppType(), `QFlags<`) {
if strings.HasPrefix(p.ParameterType, `QFlags<`) ||
strings.HasPrefix(p.GetQtCppType().ParameterType, `QFlags<`) {
return true // This catches most cases through the typedef system
}

View File

@ -18,12 +18,17 @@ func applyTypedefs(p CppParameter) CppParameter {
t2 := applyTypedefs(t) // recursive
// Wipe out so that RenderTypeQtCpp() does not see it
t2.QtCppOriginalType = ""
t2.QtCppOriginalType = nil
// QListOf returns for either QList< or QVector<
// Patch it up to the first < position and last character
bpos := strings.Index(p.ParameterType, `<`)
p.AssignAlias(p.ParameterType[0:bpos] + `<` + t2.RenderTypeQtCpp() + `>`)
if p.QtCppOriginalType == nil {
tmp := p // copy
p.QtCppOriginalType = &tmp
}
p.ParameterType = p.ParameterType[0:bpos] + `<` + t2.RenderTypeQtCpp() + `>`
}
return p

View File

@ -735,43 +735,43 @@ QByteArray* QByteArray_FromPercentEncoding(QByteArray* pctEncoded) {
}
char* QByteArray_Begin(QByteArray* self) {
QByteArray::iterator* _ret = self->begin();
QByteArray::iterator _ret = self->begin();
return static_cast<char*>(_ret);
}
const char* QByteArray_Begin2(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->begin();
return static_cast<const char*>(_ret);
QByteArray::const_iterator _ret = self->begin();
return const_cast<const char*>(static_cast<const char*>(_ret));
}
const char* QByteArray_Cbegin(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->cbegin();
return static_cast<const char*>(_ret);
QByteArray::const_iterator _ret = self->cbegin();
return const_cast<const char*>(static_cast<const char*>(_ret));
}
const char* QByteArray_ConstBegin(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->constBegin();
return static_cast<const char*>(_ret);
QByteArray::const_iterator _ret = self->constBegin();
return const_cast<const char*>(static_cast<const char*>(_ret));
}
char* QByteArray_End(QByteArray* self) {
QByteArray::iterator* _ret = self->end();
QByteArray::iterator _ret = self->end();
return static_cast<char*>(_ret);
}
const char* QByteArray_End2(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->end();
return static_cast<const char*>(_ret);
QByteArray::const_iterator _ret = self->end();
return const_cast<const char*>(static_cast<const char*>(_ret));
}
const char* QByteArray_Cend(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->cend();
return static_cast<const char*>(_ret);
QByteArray::const_iterator _ret = self->cend();
return const_cast<const char*>(static_cast<const char*>(_ret));
}
const char* QByteArray_ConstEnd(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->constEnd();
return static_cast<const char*>(_ret);
QByteArray::const_iterator _ret = self->constEnd();
return const_cast<const char*>(static_cast<const char*>(_ret));
}
void QByteArray_PushBack(QByteArray* self, char c) {

View File

@ -52,23 +52,23 @@ bool QRegion_IsNull(const QRegion* self) {
}
QRect* QRegion_Begin(const QRegion* self) {
const QRegion::const_iterator* _ret = self->begin();
return static_cast<QRect*>(_ret);
QRegion::const_iterator _ret = self->begin();
return const_cast<QRect*>(static_cast<const QRect*>(_ret));
}
QRect* QRegion_Cbegin(const QRegion* self) {
const QRegion::const_iterator* _ret = self->cbegin();
return static_cast<QRect*>(_ret);
QRegion::const_iterator _ret = self->cbegin();
return const_cast<QRect*>(static_cast<const QRect*>(_ret));
}
QRect* QRegion_End(const QRegion* self) {
const QRegion::const_iterator* _ret = self->end();
return static_cast<QRect*>(_ret);
QRegion::const_iterator _ret = self->end();
return const_cast<QRect*>(static_cast<const QRect*>(_ret));
}
QRect* QRegion_Cend(const QRegion* self) {
const QRegion::const_iterator* _ret = self->cend();
return static_cast<QRect*>(_ret);
QRegion::const_iterator _ret = self->cend();
return const_cast<QRect*>(static_cast<const QRect*>(_ret));
}
bool QRegion_Contains(const QRegion* self, QPoint* p) {

View File

@ -25,8 +25,8 @@ size_t QStringView_Size(const QStringView* self) {
}
QChar* QStringView_Data(const QStringView* self) {
const QStringView::const_pointer* _ret = self->data();
return static_cast<QChar*>(_ret);
QStringView::const_pointer _ret = self->data();
return const_cast<QChar*>(static_cast<const QChar*>(_ret));
}
QChar* QStringView_OperatorSubscript(const QStringView* self, size_t n) {
@ -164,23 +164,23 @@ double QStringView_ToDouble(const QStringView* self) {
}
QChar* QStringView_Begin(const QStringView* self) {
const QStringView::const_iterator* _ret = self->begin();
return static_cast<QChar*>(_ret);
QStringView::const_iterator _ret = self->begin();
return const_cast<QChar*>(static_cast<const QChar*>(_ret));
}
QChar* QStringView_End(const QStringView* self) {
const QStringView::const_iterator* _ret = self->end();
return static_cast<QChar*>(_ret);
QStringView::const_iterator _ret = self->end();
return const_cast<QChar*>(static_cast<const QChar*>(_ret));
}
QChar* QStringView_Cbegin(const QStringView* self) {
const QStringView::const_iterator* _ret = self->cbegin();
return static_cast<QChar*>(_ret);
QStringView::const_iterator _ret = self->cbegin();
return const_cast<QChar*>(static_cast<const QChar*>(_ret));
}
QChar* QStringView_Cend(const QStringView* self) {
const QStringView::const_iterator* _ret = self->cend();
return static_cast<QChar*>(_ret);
QStringView::const_iterator _ret = self->cend();
return const_cast<QChar*>(static_cast<const QChar*>(_ret));
}
bool QStringView_Empty(const QStringView* self) {