diff --git a/cmd/genbindings/clang2il.go b/cmd/genbindings/clang2il.go index 29e34e7b..c4b4d559 100644 --- a/cmd/genbindings/clang2il.go +++ b/cmd/genbindings/clang2il.go @@ -491,7 +491,7 @@ func parseMethod(node map[string]interface{}, mm *CppMethod) error { // If anything here is too complicated, skip the whole method var err error = nil - mm.ReturnType, mm.Parameters, err = parseTypeString(qualType) + mm.ReturnType, mm.Parameters, mm.IsConst, err = parseTypeString(qualType) if err != nil { return err } @@ -575,15 +575,15 @@ func parseMethod(node map[string]interface{}, mm *CppMethod) error { } // parseTypeString converts a function/method type string such as -// - `QString (const char *, const char *, int)` +// - `QString (const char *, const char *, int) const` // - `void (const QKeySequence \u0026)` // into its (A) return type and (B) separate parameter types. // These clang strings never contain the parameter's name, so the names here are // not filled in. -func parseTypeString(typeString string) (CppParameter, []CppParameter, error) { +func parseTypeString(typeString string) (CppParameter, []CppParameter, bool, error) { if strings.Contains(typeString, `&&`) { // TODO Rvalue references - return CppParameter{}, nil, ErrTooComplex + return CppParameter{}, nil, false, ErrTooComplex } // Cut to exterior-most (, ) pair @@ -591,7 +591,12 @@ func parseTypeString(typeString string) (CppParameter, []CppParameter, error) { epos := strings.LastIndex(typeString, `)`) if opos == -1 || epos == -1 { - return CppParameter{}, nil, fmt.Errorf("Type string %q missing brackets", typeString) + return CppParameter{}, nil, false, fmt.Errorf("Type string %q missing brackets", typeString) + } + + isConst := false + if strings.Contains(typeString[epos:], `const`) { + isConst = true } returnType := parseSingleTypeString(strings.TrimSpace(typeString[0:opos])) @@ -599,14 +604,14 @@ func parseTypeString(typeString string) (CppParameter, []CppParameter, error) { // Skip functions that return ints-by-reference since the ergonomics don't // go through the binding if returnType.IntType() && returnType.ByRef { - return CppParameter{}, nil, ErrTooComplex // e.g. QSize::rheight() + return CppParameter{}, nil, false, ErrTooComplex // e.g. QSize::rheight() } inner := typeString[opos+1 : epos] // Should be no more brackets if strings.ContainsAny(inner, `()`) { - return CppParameter{}, nil, ErrTooComplex + return CppParameter{}, nil, false, ErrTooComplex } // Parameters are separated by commas and nesting can not be possible @@ -622,7 +627,7 @@ func parseTypeString(typeString string) (CppParameter, []CppParameter, error) { } } - return returnType, ret, nil + return returnType, ret, isConst, nil } func tokenizeMultipleParameters(p string) []string { diff --git a/cmd/genbindings/emitcabi.go b/cmd/genbindings/emitcabi.go index e0dfd813..2453faf7 100644 --- a/cmd/genbindings/emitcabi.go +++ b/cmd/genbindings/emitcabi.go @@ -600,7 +600,13 @@ extern "C" { } } else if m.ReturnType.QtClassType() && !m.ReturnType.Pointer { - shouldReturn = m.ReturnType.ParameterType + " ret = " + // Still need const/nonconst in order to properly call function overloads that are only disambiguated by const-ness + // e.g. QCborArray::begin() can return an Iterator or a ConstIterator + if m.IsConst { + shouldReturn = "const " + m.ReturnType.ParameterType + " ret = " + } else { + shouldReturn = m.ReturnType.ParameterType + " ret = " + } afterCall = "\t// Copy-construct value returned type into heap-allocated copy\n" afterCall += "\treturn static_cast<" + m.ReturnType.ParameterType + "*>(new " + m.ReturnType.ParameterType + "(ret));\n" diff --git a/cmd/genbindings/intermediate.go b/cmd/genbindings/intermediate.go index 1f72b92c..636ea30f 100644 --- a/cmd/genbindings/intermediate.go +++ b/cmd/genbindings/intermediate.go @@ -159,6 +159,7 @@ type CppMethod struct { Parameters []CppParameter IsStatic bool IsSignal bool + IsConst bool HasHiddenParams bool // Set to true if there is an overload with more parameters }