Skip to content
This repository has been archived by the owner on May 18, 2024. It is now read-only.

Commit

Permalink
global static variable: allow unknown array length
Browse files Browse the repository at this point in the history
  • Loading branch information
xushiwei committed Jul 16, 2022
1 parent 8ffa161 commit 4956803
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 6 deletions.
24 changes: 20 additions & 4 deletions cl/type_and_var.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,25 @@ func toType(ctx *blockCtx, typ *ast.Type, flags int) types.Type {
}

func toTypeEx(ctx *blockCtx, scope *types.Scope, tyAnonym types.Type, typ *ast.Type, flags int) (t types.Type, kind int) {
t, kind, err := parseType(ctx, scope, tyAnonym, typ, flags)
if err != nil {
log.Panicln("toType:", err, "-", typ.QualType)
}
return
}

func parseType(ctx *blockCtx, scope *types.Scope, tyAnonym types.Type, typ *ast.Type, flags int) (t types.Type, kind int, err error) {
conf := &parser.Config{
Pkg: ctx.pkg.Types, Scope: scope, Flags: flags,
TyAnonym: tyAnonym, TyInt128: ctx.tyI128, TyUint128: ctx.tyU128,
}
retry:
t, kind, err := parser.ParseType(typ.QualType, conf)
t, kind, err = parser.ParseType(typ.QualType, conf)
if err != nil {
if e, ok := err.(*parser.TypeNotFound); ok && e.StructOrUnion {
ctx.typdecls[e.Literal] = ctx.cb.NewType(e.Literal)
goto retry
}
log.Panicln("toType:", err, "-", typ.QualType)
}
return
}
Expand Down Expand Up @@ -258,17 +265,26 @@ func compileVarDecl(ctx *blockCtx, decl *ast.Node, global bool) {
scope := ctx.cb.Scope()
flags := 0
static := ""
gblStatic := false
switch decl.StorageClass {
case ast.Extern:
flags = parser.FlagIsExtern
case ast.Static:
if !global { // local static variable
if global { // global static
gblStatic = true
} else { // local static variable
scope = ctx.pkg.Types.Scope()
}
static = decl.Name
decl.Name = ctx.autoStaticName(static)
}
typ, kind := toTypeEx(ctx, scope, nil, decl.Type, flags)
typ, kind, err := parseType(ctx, scope, nil, decl.Type, flags)
if err != nil {
if gblStatic && parser.IsArrayWithoutLen(err) {
return
}
log.Panicln("parseType:", err, "-", decl.Type)
}
avoidKeyword(&decl.Name)
if flags == parser.FlagIsExtern {
scope.Insert(types.NewVar(ctx.goNodePos(decl), ctx.pkg.Types, decl.Name, typ))
Expand Down
13 changes: 12 additions & 1 deletion clang/types/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import (
"github.com/goplus/gox"
)

const (
emsgDefArrWithoutLen = "define array without length"
)

var (
ErrInvalidType = errors.New("invalid type")
)
Expand All @@ -36,6 +40,13 @@ func (p *ParseTypeError) Error() string {
return p.ErrMsg // TODO
}

func IsArrayWithoutLen(err error) bool {
if e, ok := err.(*ParseTypeError); ok {
return e.ErrMsg == emsgDefArrWithoutLen
}
return false
}

// -----------------------------------------------------------------------------

const (
Expand Down Expand Up @@ -266,7 +277,7 @@ func (p *parser) parseArray(t types.Type, inFlags int) (types.Type, error) {
if n >= 0 || (inFlags&(FlagIsExtern|FlagIsTypedef|FlagIsParam)) != 0 {
t = types.NewArray(t, n)
} else {
return nil, p.newError("define array without length")
return nil, p.newError(emsgDefArrWithoutLen)
}
return t, nil
}
Expand Down
14 changes: 14 additions & 0 deletions clang/types/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ var cases = []testCase{
{qualType: "const char [7]", flags: FlagIsParam, typ: tyCharPtr},
{qualType: "char []", flags: FlagIsField, typ: types.NewArray(tyChar, 0)},
{qualType: "char []", flags: FlagIsExtern, typ: types.NewArray(tyChar, -1)},
{qualType: "char []", flags: 0, err: emsgDefArrWithoutLen},
{qualType: "char []", flags: FlagIsTypedef, typ: types.NewArray(tyChar, -1)},
{qualType: "char []", flags: FlagIsParam, typ: tyCharPtr},
{qualType: "int [100][3]", typ: tyInt3_100},
Expand Down Expand Up @@ -201,3 +202,16 @@ func errMsgOf(err error) string {
}

// -----------------------------------------------------------------------------

func TestIsArrayWithoutLen(t *testing.T) {
_, _, err := ParseType("byte[]", &Config{Scope: types.Universe})
if !IsArrayWithoutLen(err) {
t.Fatal("ParseType:", err)
}
_, _, err = ParseType("byte[]", &Config{Scope: types.Universe, Flags: FlagIsExtern})
if IsArrayWithoutLen(err) {
t.Fatal("ParseType:", err)
}
}

// -----------------------------------------------------------------------------
4 changes: 3 additions & 1 deletion testdata/init/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

int g_a = 100;

int g_arr[100][3];
static int g_arr[][3];
static int g_arr[100][3];

int (*g_parr)[100][3] = &g_arr;

union { int a; unsigned short b; } g_foo = { 1 };
Expand Down

0 comments on commit 4956803

Please sign in to comment.