Skip to content

Commit

Permalink
gogensig:check methods redefine
Browse files Browse the repository at this point in the history
  • Loading branch information
luoliwoshang committed Jan 3, 2025
1 parent 2c1d093 commit ee49d15
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 10 deletions.
7 changes: 7 additions & 0 deletions cmd/gogensig/convert/_testdata/gpgerror/conf/llcppg.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "gpgerror",
"libs": "$(pkg-config --libs gpg-error)",
"include": ["gpg-error.h","gpgrt.h"],
"trimPrefixes": ["gpg_err_","gpgrt_set_","gpg_","GPG_ERR_"],
"cplusplus":false
}
42 changes: 42 additions & 0 deletions cmd/gogensig/convert/_testdata/gpgerror/conf/llcppg.symb.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
[
{
"mangle": "gpg_strerror",
"c++": "gpg_strerror",
"go": "ErrorT.Strerror"
},
{
"mangle": "gpg_strerror_r",
"c++": "gpg_strerror_r",
"go": "ErrorT.StrerrorR"
},
{
"mangle": "gpg_strsource",
"c++": "gpg_strsource",
"go": "ErrorT.Strsource"
},
{
"mangle":"gpgrt_lock_init",
"c++":"gpgrt_lock_init",
"go":"(*GpgrtLockT).LockInit"
},
{
"mangle":"gpgrt_lock_lock",
"c++":"gpgrt_lock_lock",
"go":"(*GpgrtLockT).LockLock"
},
{
"mangle":"gpgrt_lock_trylock",
"c++":"gpgrt_lock_trylock",
"go":"(*GpgrtLockT).LockTrylock"
},
{
"mangle":"gpgrt_lock_unlock",
"c++":"gpgrt_lock_unlock",
"go":"(*GpgrtLockT).LockUnlock"
},
{
"mangle":"gpgrt_lock_destroy",
"c++":"gpgrt_lock_destroy",
"go":"(*GpgrtLockT).LockDestroy"
}
]
72 changes: 72 additions & 0 deletions cmd/gogensig/convert/_testdata/gpgerror/gogensig.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
===== gpg-error.go =====
package gpgerror

import (
"github.com/goplus/llgo/c"
_ "unsafe"
)

type ErrorT c.Uint
// llgo:link ErrorT.Strerror C.gpg_strerror
func (recv_ ErrorT) Strerror() *int8 {
return nil
}
// llgo:link ErrorT.StrerrorR C.gpg_strerror_r
func (recv_ ErrorT) StrerrorR(buf *int8, buflen uintptr) c.Int {
return 0
}
// llgo:link ErrorT.Strsource C.gpg_strsource
func (recv_ ErrorT) Strsource() *int8 {
return nil
}

type CodeT c.Int

const (
CodeTNOERROR CodeT = 0
CodeTGENERAL CodeT = 1
CodeTUNKNOWNPACKET CodeT = 2
CodeTCODEDIM CodeT = 65536
)

type GpgrtLockT struct {
X_Vers c.Long
U struct {
X_Priv [64]int8
}
}
// llgo:link (*GpgrtLockT).LockInit C.gpgrt_lock_init
func (recv_ *GpgrtLockT) LockInit() CodeT {
return 0
}
// llgo:link (*GpgrtLockT).LockLock C.gpgrt_lock_lock
func (recv_ *GpgrtLockT) LockLock() CodeT {
return 0
}
// llgo:link (*GpgrtLockT).LockTrylock C.gpgrt_lock_trylock
func (recv_ *GpgrtLockT) LockTrylock() CodeT {
return 0
}
// llgo:link (*GpgrtLockT).LockUnlock C.gpgrt_lock_unlock
func (recv_ *GpgrtLockT) LockUnlock() CodeT {
return 0
}
// llgo:link (*GpgrtLockT).LockDestroy C.gpgrt_lock_destroy
func (recv_ *GpgrtLockT) LockDestroy() CodeT {
return 0
}

===== gpgerror_autogen_link.go =====
package gpgerror

const LLGoPackage string = "link: $(pkg-config --libs gpg-error);"

===== gpgrt.go =====
package gpgerror

import _ "unsafe"

===== llcppg.pub =====
gpg_err_code_t CodeT
gpg_error_t ErrorT
gpgrt_lock_t GpgrtLockT
57 changes: 57 additions & 0 deletions cmd/gogensig/convert/_testdata/gpgerror/hfile/gpg-error.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <stddef.h>
/* The error value type gpg_error_t. */

/* We would really like to use bit-fields in a struct, but using
* structs as return values can cause binary compatibility issues, in
* particular if you want to do it efficiently (also see
* -freg-struct-return option to GCC). */
typedef unsigned int gpg_error_t;
/* String functions. */

/* Return a pointer to a string containing a description of the error
* code in the error value ERR. This function is not thread-safe. */
const char *gpg_strerror (gpg_error_t err);

/* Return the error string for ERR in the user-supplied buffer BUF of
* size BUFLEN. This function is, in contrast to gpg_strerror,
* thread-safe if a thread-safe strerror_r() function is provided by
* the system. If the function succeeds, 0 is returned and BUF
* contains the string describing the error. If the buffer was not
* large enough, ERANGE is returned and BUF contains as much of the
* beginning of the error string as fits into the buffer. */
int gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen);

/* Return a pointer to a string containing a description of the error
* source in the error value ERR. */
const char *gpg_strsource (gpg_error_t err);

/* Only use free slots, never change or reorder the existing
* entries. */
typedef enum
{
GPG_ERR_NO_ERROR = 0,
GPG_ERR_GENERAL = 1,
GPG_ERR_UNKNOWN_PACKET = 2,
/* This is one more than the largest allowed entry. */
GPG_ERR_CODE_DIM = 65536
} gpg_err_code_t;

typedef struct
{
long _vers;
union {
volatile char _priv[64];
long _x_align;
long *_xp_align;
} u;
} gpgrt_lock_t;



/* NB: If GPGRT_LOCK_DEFINE is not used, zero out the lock variable
before passing it to gpgrt_lock_init. */
gpg_err_code_t gpgrt_lock_init (gpgrt_lock_t *lockhd);
gpg_err_code_t gpgrt_lock_lock (gpgrt_lock_t *lockhd);
gpg_err_code_t gpgrt_lock_trylock (gpgrt_lock_t *lockhd);
gpg_err_code_t gpgrt_lock_unlock (gpgrt_lock_t *lockhd);
gpg_err_code_t gpgrt_lock_destroy (gpgrt_lock_t *lockhd);
56 changes: 56 additions & 0 deletions cmd/gogensig/convert/_testdata/gpgerror/hfile/gpgrt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <stddef.h>
/* The error value type gpg_error_t. */

/* We would really like to use bit-fields in a struct, but using
* structs as return values can cause binary compatibility issues, in
* particular if you want to do it efficiently (also see
* -freg-struct-return option to GCC). */
typedef unsigned int gpg_error_t;

/* String functions. */

/* Return a pointer to a string containing a description of the error
* code in the error value ERR. This function is not thread-safe. */
const char *gpg_strerror (gpg_error_t err);

/* Return the error string for ERR in the user-supplied buffer BUF of
* size BUFLEN. This function is, in contrast to gpg_strerror,
* thread-safe if a thread-safe strerror_r() function is provided by
* the system. If the function succeeds, 0 is returned and BUF
* contains the string describing the error. If the buffer was not
* large enough, ERANGE is returned and BUF contains as much of the
* beginning of the error string as fits into the buffer. */
int gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen);

/* Return a pointer to a string containing a description of the error
* source in the error value ERR. */
const char *gpg_strsource (gpg_error_t err);

typedef struct
{
long _vers;
union {
volatile char _priv[64];
long _x_align;
long *_xp_align;
} u;
} gpgrt_lock_t;

/* Only use free slots, never change or reorder the existing
* entries. */
typedef enum
{
GPG_ERR_NO_ERROR = 0,
GPG_ERR_GENERAL = 1,
GPG_ERR_UNKNOWN_PACKET = 2,
/* This is one more than the largest allowed entry. */
GPG_ERR_CODE_DIM = 65536
} gpg_err_code_t;

/* NB: If GPGRT_LOCK_DEFINE is not used, zero out the lock variable
before passing it to gpgrt_lock_init. */
gpg_err_code_t gpgrt_lock_init (gpgrt_lock_t *lockhd);
gpg_err_code_t gpgrt_lock_lock (gpgrt_lock_t *lockhd);
gpg_err_code_t gpgrt_lock_trylock (gpgrt_lock_t *lockhd);
gpg_err_code_t gpgrt_lock_unlock (gpgrt_lock_t *lockhd);
gpg_err_code_t gpgrt_lock_destroy (gpgrt_lock_t *lockhd);
46 changes: 36 additions & 10 deletions cmd/gogensig/convert/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,9 @@ func (p *Package) newReceiver(typ *ast.FuncType) *types.Var {
return p.p.NewParam(token.NoPos, "recv_", recvType)
}

func (p *Package) ToSigSignature(fnSpec *GoFuncSpec, funcDecl *ast.FuncDecl) (*types.Signature, error) {
func (p *Package) ToSigSignature(recv *types.Var, funcDecl *ast.FuncDecl) (*types.Signature, error) {
var sig *types.Signature
var recv *types.Var
var err error
if fnSpec.IsMethod &&
funcDecl.Type.Params.List != nil &&
len(funcDecl.Type.Params.List) > 0 {
recv = p.newReceiver(funcDecl.Type)
}
sig, err = p.cvt.ToSignature(funcDecl.Type, recv)
if err != nil {
return nil, err
Expand Down Expand Up @@ -248,16 +242,48 @@ func (p *Package) NewFuncDecl(funcDecl *ast.FuncDecl) error {
// not gen the function not in the symbolmap
return err
}
if obj := p.p.Types.Scope().Lookup(fnSpec.FnName); obj != nil {
return errs.NewFuncAlreadyDefinedError(fnSpec.GoSymbName)

recv, err := p.funcIsDefined(fnSpec, funcDecl)
if err != nil {
return err
}
sig, err := p.ToSigSignature(fnSpec, funcDecl)

sig, err := p.ToSigSignature(recv, funcDecl)
if err != nil {
return err
}
return p.handleFuncDecl(fnSpec, sig, funcDecl)
}

func (p *Package) funcIsDefined(fnSpec *GoFuncSpec, funcDecl *ast.FuncDecl) (recv *types.Var, err error) {
if fnSpec.IsMethod &&
funcDecl.Type.Params.List != nil &&
len(funcDecl.Type.Params.List) > 0 {
recv = p.newReceiver(funcDecl.Type)

var namedType *types.Named
switch t := recv.Type().(type) {
case *types.Named:
namedType = t
case *types.Pointer:
if named, ok := t.Elem().(*types.Named); ok {
namedType = named
}
}
methodName := fnSpec.FnName
for i := 0; i < namedType.NumMethods(); i++ {
if namedType.Method(i).Name() == methodName {
return nil, errs.NewFuncAlreadyDefinedError(fnSpec.GoSymbName)
}
}
} else {
if obj := p.p.Types.Scope().Lookup(fnSpec.FnName); obj != nil {
return nil, errs.NewFuncAlreadyDefinedError(fnSpec.GoSymbName)
}
}
return
}

// NewTypeDecl converts C/C++ type declarations to Go.
// Besides regular type declarations, it also supports:
// - Forward declarations: Pre-registers incomplete types for later definition
Expand Down

0 comments on commit ee49d15

Please sign in to comment.