mirror of
https://github.com/mappu/miqt.git
synced 2024-12-22 08:58:37 +00:00
genbindings: remove uintptr fallbacks for more and accurate enum/typedef handling
This commit is contained in:
parent
b7a488dac0
commit
99aaf69b13
@ -55,9 +55,9 @@ func (p CppParameter) RenderTypeCabi() string {
|
||||
ret = "size_t"
|
||||
case "qreal":
|
||||
ret = "double"
|
||||
case "qintptr":
|
||||
case "qintptr", "QIntegerForSizeof<void *>::Signed":
|
||||
ret = "intptr_t"
|
||||
case "quintptr", "uintptr":
|
||||
case "quintptr", "uintptr", "QIntegerForSizeof<void *>::Unsigned":
|
||||
ret = "uintptr_t"
|
||||
case "qptrdiff":
|
||||
ret = "ptrdiff_t"
|
||||
@ -76,9 +76,6 @@ func (p CppParameter) RenderTypeCabi() string {
|
||||
} else if e, ok := KnownEnums[p.ParameterType]; ok {
|
||||
ret = e.UnderlyingType.RenderTypeCabi()
|
||||
|
||||
} else if strings.Contains(p.ParameterType, `::`) {
|
||||
// Inner class
|
||||
ret = cabiClassName(p.ParameterType)
|
||||
}
|
||||
|
||||
if p.Pointer {
|
||||
@ -91,7 +88,7 @@ func (p CppParameter) RenderTypeCabi() string {
|
||||
}
|
||||
|
||||
func (p CppParameter) RenderTypeQtCpp() string {
|
||||
cppType := p.UnderlyingType()
|
||||
cppType := p.GetQtCppType()
|
||||
|
||||
if p.Const {
|
||||
cppType = "const " + cppType
|
||||
@ -212,6 +209,9 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
|
||||
// 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
|
||||
@ -366,19 +366,19 @@ 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.Const {
|
||||
shouldReturn += "(" + p.RenderTypeCabi() + ") "
|
||||
|
||||
} else if p.IsFlagType() {
|
||||
// Needs an explicit int cast
|
||||
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
|
||||
afterCall += indent + "" + assignExpression + "static_cast<int>(" + namePrefix + "_ret);\n"
|
||||
|
||||
} else if p.IsKnownEnum() {
|
||||
} 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"
|
||||
|
||||
} else if p.Const {
|
||||
shouldReturn += "(" + p.RenderTypeCabi() + ") "
|
||||
|
||||
}
|
||||
|
||||
return indent + shouldReturn + rvalue + ";\n" + afterCall
|
||||
|
@ -82,21 +82,20 @@ func (p CppParameter) RenderTypeGo() string {
|
||||
} else {
|
||||
ret += "uint64"
|
||||
}
|
||||
case "qintptr", "uintptr_t", "intptr_t", "quintptr":
|
||||
case "qintptr", "uintptr_t", "intptr_t", "quintptr", "QIntegerForSizeof<void *>::Unsigned", "QIntegerForSizeof<void *>::Signed":
|
||||
ret += "uintptr"
|
||||
default:
|
||||
|
||||
if p.IsFlagType() {
|
||||
ret += "int"
|
||||
|
||||
} else if strings.Contains(p.ParameterType, `::`) {
|
||||
if p.IsKnownEnum() {
|
||||
ret += cabiClassName(p.ParameterType)
|
||||
} else if p.IsKnownEnum() {
|
||||
ret += cabiClassName(p.ParameterType)
|
||||
|
||||
} else if strings.Contains(p.ParameterType, `::`) {
|
||||
// Inner class
|
||||
ret += cabiClassName(p.ParameterType)
|
||||
|
||||
} else {
|
||||
// Inner class
|
||||
ret += cabiClassName(p.ParameterType)
|
||||
}
|
||||
} else {
|
||||
// Do not transform this type
|
||||
ret += p.ParameterType
|
||||
@ -371,7 +370,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
|
||||
}
|
||||
}
|
||||
|
||||
} else if rt.IntType() || rt.ParameterType == "bool" {
|
||||
} else if rt.IntType() || rt.IsKnownEnum() || rt.IsFlagType() || rt.ParameterType == "bool" || rt.QtCppOriginalType != "" {
|
||||
// Need to cast Cgo type to Go int type
|
||||
// Optimize assignment to avoid temporary
|
||||
return assignExpr + "(" + rt.RenderTypeGo() + ")(" + rvalue + ")\n"
|
||||
|
@ -107,6 +107,18 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
|
||||
if strings.HasPrefix(p.ParameterType, "StringResult<") {
|
||||
return ErrTooComplex // e.g. qcborstreamreader.h
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "QScopedPointer<") {
|
||||
return ErrTooComplex // e.g. qbrush.h
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "QExplicitlySharedDataPointer<") {
|
||||
return ErrTooComplex // e.g. qpicture.h
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "QSharedDataPointer<") {
|
||||
return ErrTooComplex // e.g. qurlquery.h
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "QTypedArrayData<") {
|
||||
return ErrTooComplex // e.g. qbitarray.h
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "QGenericMatrix<") {
|
||||
return ErrTooComplex // e.g. qmatrix4x4.h
|
||||
}
|
||||
@ -130,9 +142,13 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
|
||||
if strings.Contains(p.ParameterType, `::QPrivate`) {
|
||||
return ErrTooComplex // e.g. QAbstractItemModel::QPrivateSignal
|
||||
}
|
||||
if strings.Contains(p.GetQtCppType(), `::DataPtr`) {
|
||||
return ErrTooComplex // e.g. QImage::data_ptr()
|
||||
}
|
||||
|
||||
// Some QFoo constructors take a QFooPrivate
|
||||
if p.ParameterType[0] == 'Q' && strings.HasSuffix(p.ParameterType, "Private") && !isReturnType {
|
||||
// QIcon also returns a QIconPrivate
|
||||
if p.ParameterType[0] == 'Q' && strings.HasSuffix(p.ParameterType, "Private") {
|
||||
return ErrTooComplex
|
||||
}
|
||||
|
||||
@ -217,11 +233,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.TypeAlias == "Q_PID" {
|
||||
if p.GetQtCppType() == "Q_PID" {
|
||||
return true // int64 on Linux, _PROCESS_INFORMATION* on Windows
|
||||
}
|
||||
|
||||
if p.ParameterType == "QSocketDescriptor::DescriptorType" {
|
||||
if p.GetQtCppType() == "QSocketDescriptor::DescriptorType" {
|
||||
return true // uintptr_t-compatible on Linux, void* on Windows
|
||||
}
|
||||
return false
|
||||
|
@ -25,38 +25,44 @@ func init() {
|
||||
// QString is deleted from this binding
|
||||
KnownTypedefs["QStringList"] = CppTypedef{"QStringList", parseSingleTypeString("QList<QString>")}
|
||||
|
||||
// Not sure why this isn't picked up automatically
|
||||
// FIXME because QFile inherits QFileDevice(!!) and the name refers to its parent class
|
||||
KnownTypedefs["QFile::FileTime"] = CppTypedef{"QFile::FileTime", parseSingleTypeString("QFileDevice::FileTime")}
|
||||
|
||||
// n.b. Qt 5 only
|
||||
KnownTypedefs["QLineF::IntersectionType"] = CppTypedef{"QLineF::IntersectionType", parseSingleTypeString("QLineF::IntersectType")}
|
||||
|
||||
// Not sure the reason for this one
|
||||
KnownTypedefs["QSocketDescriptor::DescriptorType"] = CppTypedef{"QSocketDescriptor::DescriptorType", parseSingleTypeString("QSocketNotifier::Type")}
|
||||
}
|
||||
|
||||
type CppParameter struct {
|
||||
ParameterName string
|
||||
ParameterType string
|
||||
TypeAlias string // If we rewrote QStringList->QList<String>, this field contains the original QStringList
|
||||
Const bool
|
||||
Pointer bool
|
||||
PointerCount int
|
||||
ByRef bool
|
||||
Optional bool
|
||||
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
|
||||
}
|
||||
|
||||
func (p *CppParameter) AssignAlias(newType string) {
|
||||
if p.TypeAlias == "" {
|
||||
p.TypeAlias = p.ParameterType // Overwrite once only, at the earliest base type
|
||||
if p.QtCppOriginalType == "" {
|
||||
p.QtCppOriginalType = p.ParameterType // Overwrite once only, at the earliest base type
|
||||
}
|
||||
p.ParameterType = newType
|
||||
}
|
||||
|
||||
func (p *CppParameter) CopyWithAlias(alias CppParameter) CppParameter {
|
||||
ret := *p // copy
|
||||
ret.ParameterName = alias.ParameterName
|
||||
ret.TypeAlias = alias.ParameterType
|
||||
func (p *CppParameter) ApplyTypedef(matchedUnderlyingType CppParameter) {
|
||||
p.AssignAlias(matchedUnderlyingType.ParameterType)
|
||||
|
||||
// If this was a pointer to a typedef'd type, or a typedef of a pointer type, we need to preserve that
|
||||
// WARNING: This can't work for double indirection
|
||||
ret.Const = ret.Const || alias.Const
|
||||
ret.Pointer = ret.Pointer || alias.Pointer
|
||||
ret.PointerCount += alias.PointerCount
|
||||
ret.ByRef = ret.ByRef || alias.ByRef
|
||||
return ret
|
||||
p.Const = p.Const || matchedUnderlyingType.Const
|
||||
p.Pointer = p.Pointer || matchedUnderlyingType.Pointer
|
||||
p.PointerCount += matchedUnderlyingType.PointerCount
|
||||
p.ByRef = p.ByRef || matchedUnderlyingType.ByRef
|
||||
p.Optional = p.Optional || matchedUnderlyingType.Optional
|
||||
}
|
||||
|
||||
func (p *CppParameter) PointerTo() CppParameter {
|
||||
@ -72,9 +78,9 @@ func (p *CppParameter) ConstCast(isConst bool) CppParameter {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p *CppParameter) UnderlyingType() string {
|
||||
if p.TypeAlias != "" {
|
||||
return p.TypeAlias
|
||||
func (p *CppParameter) GetQtCppType() string {
|
||||
if p.QtCppOriginalType != "" {
|
||||
return p.QtCppOriginalType
|
||||
}
|
||||
|
||||
return p.ParameterType
|
||||
@ -85,6 +91,10 @@ func (p CppParameter) IsFlagType() bool {
|
||||
return true // This catches most cases through the typedef system
|
||||
}
|
||||
|
||||
if strings.HasPrefix(p.GetQtCppType(), `QFlags<`) {
|
||||
return true // This catches most cases through the typedef system
|
||||
}
|
||||
|
||||
switch p.ParameterType {
|
||||
case "QTouchEvent::TouchPoint::InfoFlags",
|
||||
"QFile::Permissions",
|
||||
@ -166,6 +176,7 @@ func (p CppParameter) IntType() bool {
|
||||
"longlong", "ulonglong", "qlonglong", "qulonglong", "qint64", "quint64", "int64_t", "uint64_t", "long long", "unsigned long long",
|
||||
"qintptr", "quintptr", "uintptr_t", "intptr_t",
|
||||
"qsizetype", "size_t",
|
||||
"QIntegerForSizeof<void *>::Unsigned",
|
||||
"qptrdiff", "ptrdiff_t",
|
||||
"double", "float", "qreal":
|
||||
return true
|
||||
|
@ -6,20 +6,24 @@ import (
|
||||
|
||||
func applyTypedefs(p CppParameter) CppParameter {
|
||||
|
||||
if td, ok := KnownTypedefs[p.ParameterType]; ok {
|
||||
p = td.UnderlyingType.CopyWithAlias(p)
|
||||
for {
|
||||
td, ok := KnownTypedefs[p.ParameterType]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
p.ApplyTypedef(td.UnderlyingType)
|
||||
}
|
||||
|
||||
if t, ok := p.QListOf(); ok {
|
||||
t2 := applyTypedefs(t) // recursive
|
||||
|
||||
// Wipe out so that RenderTypeQtCpp() does not see it
|
||||
t2.TypeAlias = ""
|
||||
t2.QtCppOriginalType = ""
|
||||
|
||||
// QListOf returns for either QList< or QVector<
|
||||
// Patch it up to the first < position and last character
|
||||
bpos := strings.Index(p.ParameterType, `<`)
|
||||
p.ParameterType = p.ParameterType[0:bpos] + `<` + t2.RenderTypeQtCpp() + `>`
|
||||
p.AssignAlias(p.ParameterType[0:bpos] + `<` + t2.RenderTypeQtCpp() + `>`)
|
||||
}
|
||||
|
||||
return p
|
||||
|
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -30,15 +31,44 @@ func TestTransformTypedefs(t *testing.T) {
|
||||
|
||||
runTest := func(check string, expect string) {
|
||||
parsed := makeTest(check)
|
||||
|
||||
astTransformTypedefs(&parsed)
|
||||
|
||||
got := parsed.Classes[0].Ctors[0].Parameters[0].ParameterType
|
||||
resultP := parsed.Classes[0].Ctors[0].Parameters[0]
|
||||
got := resultP.ParameterType
|
||||
|
||||
if resultP.Const {
|
||||
got = "const " + got
|
||||
}
|
||||
if resultP.Pointer {
|
||||
got += strings.Repeat("*", resultP.PointerCount)
|
||||
}
|
||||
if resultP.ByRef {
|
||||
got += "&"
|
||||
}
|
||||
|
||||
if got != expect {
|
||||
t.Errorf("Transform of WId got %q, expected %q", got, expect)
|
||||
t.Errorf("Transform of %q got %q, expected %q", check, got, expect)
|
||||
}
|
||||
}
|
||||
|
||||
runTest("WId", "uintptr_t")
|
||||
runTest("QList<WId>", "QList<uintptr_t>")
|
||||
runTest("QStringList", "QList<QString>")
|
||||
runTest("QVector<WId>", "QVector<uintptr_t>")
|
||||
|
||||
KnownTypedefs["_test_known_typedef_recursion"] = CppTypedef{"_test_known_typedef_recursion", parseSingleTypeString("WId")}
|
||||
runTest("_test_known_typedef_recursion", "uintptr_t")
|
||||
|
||||
// Pointer tests
|
||||
runTest("WId*", "uintptr_t*")
|
||||
runTest("QVector<WId*>", "QVector<uintptr_t*>")
|
||||
|
||||
// Const tests
|
||||
runTest("const QVector<WId*>", "const QVector<uintptr_t*>")
|
||||
|
||||
// Typedefs changing pointer values
|
||||
KnownTypedefs["_test_iterator"] = CppTypedef{"_test_iterator", parseSingleTypeString("char*")}
|
||||
runTest("_test_iterator", "char*")
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user