Skip to content

Commit

Permalink
clang2il.go: Check for desugared types (support clang-19+)
Browse files Browse the repository at this point in the history
* Closes #116
  • Loading branch information
rcalixte committed Jan 20, 2025
1 parent a80a939 commit 33960ee
Show file tree
Hide file tree
Showing 14 changed files with 66 additions and 325 deletions.
58 changes: 51 additions & 7 deletions cmd/genbindings/clang2il.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,47 @@ nextTopLevel:
return &ret, nil // done
}

// shouldPreferQualType returns true if we should use the qualType instead of
// the desugared type based on certain type patterns
func shouldPreferQualType(qualType string) bool {
if strings.Contains(qualType, "intptr") || strings.Contains(qualType, "_t") ||
strings.HasPrefix(qualType, "uint") || strings.Contains(qualType, "ushort") ||
strings.Contains(qualType, "quint") || strings.Contains(qualType, "qint") ||
strings.Contains(qualType, "qptrdiff") || strings.HasPrefix(qualType, "qsize") ||
strings.HasPrefix(qualType, "QIntegerForSizeof<") || strings.HasPrefix(qualType, "QPair<") {
return true
}
return false
}

// getPreferredType returns either the desugared type or qual type based on our rules
func getPreferredType(node interface{}) string {
if node == nil {
return ""
}

nodeMap, ok := node.(map[string]interface{})
if !ok {
return ""
}

var desugared, qualType string
if d, ok := nodeMap["desugaredQualType"].(string); ok {
desugared = d
}
if q, ok := nodeMap["qualType"].(string); ok {
qualType = q
}

if qualType != "" && shouldPreferQualType(qualType) {
return qualType
}
if desugared != "" {
return desugared
}
return qualType
}

// processTypedef parses a single C++ typedef into our intermediate format.
func processTypedef(node map[string]interface{}, addNamePrefix string) (CppTypedef, error) {
// Must have a name
Expand All @@ -174,7 +215,8 @@ func processTypedef(node map[string]interface{}, addNamePrefix string) (CppTyped
}

if typ, ok := node["type"].(map[string]interface{}); ok {
if qualType, ok := typ["qualType"].(string); ok {
qualType := getPreferredType(typ)
if qualType != "" {
return CppTypedef{
Alias: addNamePrefix + nodename,
UnderlyingType: parseSingleTypeString(qualType),
Expand Down Expand Up @@ -264,7 +306,8 @@ func processClassType(node map[string]interface{}, addNamePrefix string) (CppCla
}

if typ, ok := base["type"].(map[string]interface{}); ok {
if qualType, ok := typ["qualType"].(string); ok {
qualType := getPreferredType(typ)
if qualType != "" {
ret.DirectInherits = append(ret.DirectInherits, qualType)
}
}
Expand Down Expand Up @@ -512,8 +555,9 @@ func processEnum(node map[string]interface{}, addNamePrefix string) (CppEnum, er
// Underlying type
ret.UnderlyingType = parseSingleTypeString("int")
if nodefut, ok := node["fixedUnderlyingType"].(map[string]interface{}); ok {
if nodequal, ok := nodefut["qualType"].(string); ok {
ret.UnderlyingType = parseSingleTypeString(nodequal)
qualType := getPreferredType(nodefut)
if qualType != "" {
ret.UnderlyingType = parseSingleTypeString(qualType)
}
}

Expand Down Expand Up @@ -652,11 +696,11 @@ nextEnumEntry:
func parseMethod(node map[string]interface{}, mm *CppMethod) error {

if typobj, ok := node["type"].(map[string]interface{}); ok {
if qualType, ok := typobj["qualType"].(string); ok {
qualType := getPreferredType(typobj)
if qualType != "" {
// The qualType is the whole type of the method, including its parameter types
// If anything here is too complicated, skip the whole method

var err error = nil
var err error
mm.ReturnType, mm.Parameters, mm.IsConst, err = parseTypeString(qualType)
if err != nil {
return err
Expand Down
14 changes: 7 additions & 7 deletions cmd/genbindings/clang2il_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,27 @@ func TestParseMethodTypes(t *testing.T) {
}

cases := []testCase{
testCase{
{
input: "void (bool)",
expectReturn: CppParameter{ParameterType: "void"},
expectParams: []CppParameter{
CppParameter{ParameterType: "bool"},
{ParameterType: "bool"},
},
},
testCase{
{
input: "bool (QList<QPair<Foo, Bar>>, QString)",
expectReturn: CppParameter{ParameterType: "bool"},
expectParams: []CppParameter{
CppParameter{ParameterType: "QList<QPair<Foo, Bar>>"},
CppParameter{ParameterType: "QString"},
{ParameterType: "QList<QPair<Foo, Bar>>"},
{ParameterType: "QString"},
},
// expectErr: true,
},
testCase{
{
input: "bool (QList<QWidget*>)",
expectReturn: CppParameter{ParameterType: "bool"},
expectParams: []CppParameter{
CppParameter{ParameterType: "QList<QWidget*>"},
{ParameterType: "QList<QWidget*>"},
},
},
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/genbindings/transformchildclasses_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ func TestChildClassesExtract(t *testing.T) {
src := CppParsedHeader{
Classes: []CppClass{

CppClass{
{
ClassName: "Parent",

ChildClassdefs: []CppClass{

CppClass{
{
ClassName: "Parent::Child",

ChildClassdefs: []CppClass{

CppClass{
{
ClassName: "Parent::Child::Grandchild",
},
},
Expand Down
4 changes: 2 additions & 2 deletions cmd/genbindings/transformtypedefs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ func TestTransformTypedefs(t *testing.T) {
return CppParsedHeader{
Classes: []CppClass{

CppClass{
{
ClassName: "QTestClass",
Ctors: []CppMethod{

CppMethod{
{
Parameters: []CppParameter{
parseSingleTypeString(typeName),
},
Expand Down
6 changes: 3 additions & 3 deletions cmd/genbindings/util.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package main

import (
"strconv"
"encoding/json"
"log"
"strconv"
"strings"
)

Expand All @@ -12,7 +12,7 @@ func maybeSuffix(counter int) string {
return ""
}

return strconv.Itoa(counter+1)
return strconv.Itoa(counter + 1)
}

func titleCase(s string) string {
Expand Down Expand Up @@ -53,4 +53,4 @@ func slice_copy[T comparable](input []T) []T {
ret[i] = elem
}
return ret
}
}
40 changes: 0 additions & 40 deletions qt6/gen_qbrush.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
#define WORKAROUND_INNER_CLASS_DEFINITION_QGradient__QGradientData
#include <QImage>
#include <QLinearGradient>
#include <QList>
#include <QPair>
#include <QPixmap>
#include <QPointF>
#include <QRadialGradient>
Expand Down Expand Up @@ -197,44 +195,6 @@ void QGradient_SetColorAt(QGradient* self, double pos, QColor* color) {
self->setColorAt(static_cast<qreal>(pos), *color);
}

void QGradient_SetStops(QGradient* self, struct miqt_array /* of struct miqt_map tuple of double and QColor* */ stops) {
QGradientStops stops_QList;
stops_QList.reserve(stops.len);
struct miqt_map /* tuple of double and QColor* */ * stops_arr = static_cast<struct miqt_map /* tuple of double and QColor* */ *>(stops.data);
for(size_t i = 0; i < stops.len; ++i) {
QPair<double, QColor> stops_arr_i_QPair;
double* stops_arr_i_first_arr = static_cast<double*>(stops_arr[i].keys);
QColor** stops_arr_i_second_arr = static_cast<QColor**>(stops_arr[i].values);
stops_arr_i_QPair.first = static_cast<double>(stops_arr_i_first_arr[0]);
stops_arr_i_QPair.second = *(stops_arr_i_second_arr[0]);
stops_QList.push_back(stops_arr_i_QPair);
}
self->setStops(stops_QList);
}

struct miqt_array /* of struct miqt_map tuple of double and QColor* */ QGradient_Stops(const QGradient* self) {
QGradientStops _ret = self->stops();
// Convert QList<> from C++ memory to manually-managed C memory
struct miqt_map /* tuple of double and QColor* */ * _arr = static_cast<struct miqt_map /* tuple of double and QColor* */ *>(malloc(sizeof(struct miqt_map /* tuple of double and QColor* */ ) * _ret.length()));
for (size_t i = 0, e = _ret.length(); i < e; ++i) {
QPair<double, QColor> _lv_ret = _ret[i];
// Convert QPair<> from C++ memory to manually-managed C memory
double* _lv_first_arr = static_cast<double*>(malloc(sizeof(double)));
QColor** _lv_second_arr = static_cast<QColor**>(malloc(sizeof(QColor*)));
_lv_first_arr[0] = _lv_ret.first;
_lv_second_arr[0] = new QColor(_lv_ret.second);
struct miqt_map _lv_out;
_lv_out.len = 1;
_lv_out.keys = static_cast<void*>(_lv_first_arr);
_lv_out.values = static_cast<void*>(_lv_second_arr);
_arr[i] = _lv_out;
}
struct miqt_array _out;
_out.len = _ret.length();
_out.data = static_cast<void*>(_arr);
return _out;
}

int QGradient_CoordinateMode(const QGradient* self) {
QGradient::CoordinateMode _ret = self->coordinateMode();
return static_cast<int>(_ret);
Expand Down
52 changes: 0 additions & 52 deletions qt6/gen_qbrush.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,58 +544,6 @@ func (this *QGradient) SetColorAt(pos float64, color *QColor) {
C.QGradient_SetColorAt(this.h, (C.double)(pos), color.cPointer())
}

func (this *QGradient) SetStops(stops []struct {
First float64
Second QColor
}) {
stops_CArray := (*[0xffff]C.struct_miqt_map)(C.malloc(C.size_t(8 * len(stops))))
defer C.free(unsafe.Pointer(stops_CArray))
for i := range stops {
stops_i_First_CArray := (*[0xffff]C.double)(C.malloc(C.size_t(8)))
defer C.free(unsafe.Pointer(stops_i_First_CArray))
stops_i_Second_CArray := (*[0xffff]*C.QColor)(C.malloc(C.size_t(8)))
defer C.free(unsafe.Pointer(stops_i_Second_CArray))
stops_i_First_CArray[0] = (C.double)(stops[i].First)
stops_i_Second_CArray[0] = stops[i].Second.cPointer()
stops_i_pair := C.struct_miqt_map{
len: 1,
keys: unsafe.Pointer(stops_i_First_CArray),
values: unsafe.Pointer(stops_i_Second_CArray),
}
stops_CArray[i] = stops_i_pair
}
stops_ma := C.struct_miqt_array{len: C.size_t(len(stops)), data: unsafe.Pointer(stops_CArray)}
C.QGradient_SetStops(this.h, stops_ma)
}

func (this *QGradient) Stops() []struct {
First float64
Second QColor
} {
var _ma C.struct_miqt_array = C.QGradient_Stops(this.h)
_ret := make([]struct {
First float64
Second QColor
}, int(_ma.len))
_outCast := (*[0xffff]C.struct_miqt_map)(unsafe.Pointer(_ma.data)) // hey ya
for i := 0; i < int(_ma.len); i++ {
var _lv_mm C.struct_miqt_map = _outCast[i]
_lv_First_CArray := (*[0xffff]C.double)(unsafe.Pointer(_lv_mm.keys))
_lv_Second_CArray := (*[0xffff]*C.QColor)(unsafe.Pointer(_lv_mm.values))
_lv_entry_First := (float64)(_lv_First_CArray[0])

_lv_second_goptr := newQColor(_lv_Second_CArray[0])
_lv_second_goptr.GoGC() // Qt uses pass-by-value semantics for this type. Mimic with finalizer
_lv_entry_Second := *_lv_second_goptr

_ret[i] = struct {
First float64
Second QColor
}{First: _lv_entry_First, Second: _lv_entry_Second}
}
return _ret
}

func (this *QGradient) CoordinateMode() QGradient__CoordinateMode {
return (QGradient__CoordinateMode)(C.QGradient_CoordinateMode(this.h))
}
Expand Down
2 changes: 0 additions & 2 deletions qt6/gen_qbrush.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ int QGradient_Type(const QGradient* self);
void QGradient_SetSpread(QGradient* self, int spread);
int QGradient_Spread(const QGradient* self);
void QGradient_SetColorAt(QGradient* self, double pos, QColor* color);
void QGradient_SetStops(QGradient* self, struct miqt_array /* of struct miqt_map tuple of double and QColor* */ stops);
struct miqt_array /* of struct miqt_map tuple of double and QColor* */ QGradient_Stops(const QGradient* self);
int QGradient_CoordinateMode(const QGradient* self);
void QGradient_SetCoordinateMode(QGradient* self, int mode);
int QGradient_InterpolationMode(const QGradient* self);
Expand Down
40 changes: 0 additions & 40 deletions qt6/gen_qvariantanimation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
#include <QChildEvent>
#include <QEasingCurve>
#include <QEvent>
#include <QList>
#include <QMetaMethod>
#include <QMetaObject>
#include <QObject>
#include <QPair>
#include <QString>
#include <QByteArray>
#include <cstring>
Expand Down Expand Up @@ -428,44 +426,6 @@ void QVariantAnimation_SetKeyValueAt(QVariantAnimation* self, double step, QVari
self->setKeyValueAt(static_cast<qreal>(step), *value);
}

struct miqt_array /* of struct miqt_map tuple of double and QVariant* */ QVariantAnimation_KeyValues(const QVariantAnimation* self) {
QVariantAnimation::KeyValues _ret = self->keyValues();
// Convert QList<> from C++ memory to manually-managed C memory
struct miqt_map /* tuple of double and QVariant* */ * _arr = static_cast<struct miqt_map /* tuple of double and QVariant* */ *>(malloc(sizeof(struct miqt_map /* tuple of double and QVariant* */ ) * _ret.length()));
for (size_t i = 0, e = _ret.length(); i < e; ++i) {
QPair<double, QVariant> _lv_ret = _ret[i];
// Convert QPair<> from C++ memory to manually-managed C memory
double* _lv_first_arr = static_cast<double*>(malloc(sizeof(double)));
QVariant** _lv_second_arr = static_cast<QVariant**>(malloc(sizeof(QVariant*)));
_lv_first_arr[0] = _lv_ret.first;
_lv_second_arr[0] = new QVariant(_lv_ret.second);
struct miqt_map _lv_out;
_lv_out.len = 1;
_lv_out.keys = static_cast<void*>(_lv_first_arr);
_lv_out.values = static_cast<void*>(_lv_second_arr);
_arr[i] = _lv_out;
}
struct miqt_array _out;
_out.len = _ret.length();
_out.data = static_cast<void*>(_arr);
return _out;
}

void QVariantAnimation_SetKeyValues(QVariantAnimation* self, struct miqt_array /* of struct miqt_map tuple of double and QVariant* */ values) {
QVariantAnimation::KeyValues values_QList;
values_QList.reserve(values.len);
struct miqt_map /* tuple of double and QVariant* */ * values_arr = static_cast<struct miqt_map /* tuple of double and QVariant* */ *>(values.data);
for(size_t i = 0; i < values.len; ++i) {
QPair<double, QVariant> values_arr_i_QPair;
double* values_arr_i_first_arr = static_cast<double*>(values_arr[i].keys);
QVariant** values_arr_i_second_arr = static_cast<QVariant**>(values_arr[i].values);
values_arr_i_QPair.first = static_cast<double>(values_arr_i_first_arr[0]);
values_arr_i_QPair.second = *(values_arr_i_second_arr[0]);
values_QList.push_back(values_arr_i_QPair);
}
self->setKeyValues(values_QList);
}

QVariant* QVariantAnimation_CurrentValue(const QVariantAnimation* self) {
return new QVariant(self->currentValue());
}
Expand Down
Loading

0 comments on commit 33960ee

Please sign in to comment.