Skip to content

Commit

Permalink
cmd/cgo: accept expressions as untyped constants
Browse files Browse the repository at this point in the history
Fixes golang#28545

Change-Id: I31c57ce11aca651cacc72235c7753e0c0fd170ef
Reviewed-on: https://go-review.googlesource.com/c/146900
Run-TryBot: Ian Lance Taylor <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
  • Loading branch information
ianlancetaylor committed Nov 2, 2018
1 parent 745ec8b commit 4d56731
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
20 changes: 20 additions & 0 deletions misc/cgo/test/issue28545.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Failed to add type conversion for negative constant.
// No runtime test; just make sure it compiles.

package cgotest

/*
#include <complex.h>
static void issue28545F(char **p, int n, complex double a) {}
*/
import "C"

func issue28545G(p **C.char) {
C.issue28545F(p, -1, (0))
C.issue28545F(p, 2+3, complex(1, 1))
}
19 changes: 18 additions & 1 deletion src/cmd/cgo/gcc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ func (p *Package) isType(t ast.Expr) bool {
return false
}

// isConst returns whether x is an untyped constant.
// isConst returns whether x is an untyped constant expression.
func (p *Package) isConst(f *File, x ast.Expr) bool {
switch x := x.(type) {
case *ast.BasicLit:
Expand All @@ -1233,6 +1233,23 @@ func (p *Package) isConst(f *File, x ast.Expr) bool {
strings.HasPrefix(x.Name, "_Ciconst_") ||
strings.HasPrefix(x.Name, "_Cfconst_") ||
strings.HasPrefix(x.Name, "_Csconst_")
case *ast.UnaryExpr:
return p.isConst(f, x.X)
case *ast.BinaryExpr:
return p.isConst(f, x.X) && p.isConst(f, x.Y)
case *ast.ParenExpr:
return p.isConst(f, x.X)
case *ast.CallExpr:
// Calling the builtin function complex on two untyped
// constants returns an untyped constant.
// TODO: It's possible to construct a case that will
// erroneously succeed if there is a local function
// named "complex", shadowing the builtin, that returns
// a numeric type. I can't think of any cases that will
// erroneously fail.
if id, ok := x.Fun.(*ast.Ident); ok && id.Name == "complex" && len(x.Args) == 2 {
return p.isConst(f, x.Args[0]) && p.isConst(f, x.Args[1])
}
}
return false
}
Expand Down

0 comments on commit 4d56731

Please sign in to comment.