Skip to content

Commit

Permalink
gapil/analysis: Handle bitwise OR operators
Browse files Browse the repository at this point in the history
Fixes broken analysis of enums or'd together.

Fixes: #939
  • Loading branch information
ben-clayton committed Aug 22, 2017
1 parent 1aa8b7d commit 06f27fc
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 51 deletions.
101 changes: 55 additions & 46 deletions gapil/analysis/enum_value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,20 @@ func TestEnumGlobalAnalysis(t *testing.T) {
Labels: map[uint64]string{},
}},
{`cmd void c(E e) {
switch e {
case A, B, C:
G = e
}
}`, &analysis.EnumValue{
switch e {
case A, B, C:
G = e
}
}`, &analysis.EnumValue{
Numbers: u64(0, 1, 2, 3),
Labels: map[uint64]string{1: "A", 2: "B", 3: "C"},
}},
{`cmd void c(E e) {
switch e {
case A, B, C:
G = e
}
}`, &analysis.EnumValue{
switch e {
case A, B, C:
G = e
}
}`, &analysis.EnumValue{
Numbers: u64(0, 1, 2, 3),
Labels: map[uint64]string{1: "A", 2: "B", 3: "C"},
}},
Expand All @@ -83,34 +83,34 @@ func TestEnumParameterAnalysis(t *testing.T) {
expected *analysis.EnumValue
}{
{`cmd void c(E e) {
switch e {
case A, B, C: {}
}
}`, &analysis.EnumValue{
switch e {
case A, B, C: {}
}
}`, &analysis.EnumValue{
Numbers: anyU64,
Labels: map[uint64]string{1: "A", 2: "B", 3: "C"},
}}, {`cmd void c(E e) {
if e == A {}
if e == B {}
if e == C {}
}`, &analysis.EnumValue{
if e == A {}
if e == B {}
if e == C {}
}`, &analysis.EnumValue{
Numbers: anyU64,
Labels: map[uint64]string{1: "A", 2: "B", 3: "C"},
}}, {`cmd s32 c(E e) {
return switch (e) {
case A, B: 10
case C: 30
}
}`, &analysis.EnumValue{
return switch (e) {
case A, B: 10
case C: 30
}
}`, &analysis.EnumValue{
Numbers: u64(1, 2, 3),
Labels: map[uint64]string{1: "A", 2: "B", 3: "C"},
}}, {`sub s32 S(E e) {
return switch (e) {
case A, B: 10
case C: 30
}
}
cmd void c(E e) { x := S(e) }`, &analysis.EnumValue{
return switch (e) {
case A, B: 10
case C: 30
}
}
cmd void c(E e) { x := S(e) }`, &analysis.EnumValue{
Numbers: u64(1, 2, 3),
Labels: map[uint64]string{1: "A", 2: "B", 3: "C"},
}},
Expand Down Expand Up @@ -146,19 +146,28 @@ func TestBitfieldGlobalAnalysis(t *testing.T) {
Labels: map[uint64]string{},
}},
{`cmd void c(E e) {
switch e {
case A, B, C:
G = e
}
}`, &analysis.EnumValue{
switch e {
case A, B, C:
G = e
}
}`, &analysis.EnumValue{
Numbers: u64(0, 1, 2, 4),
Labels: map[uint64]string{1: "A", 2: "B", 4: "C"},
}},
{`cmd void c(E e) {
if (A in e) { G = A }
if (B in e) { G = B }
if (C in e) { G = C }
}`, &analysis.EnumValue{
if (A in e) { G = A }
if (B in e) { G = B }
if (C in e) { G = C }
}`, &analysis.EnumValue{
Numbers: u64(0, 1, 2, 4),
Labels: map[uint64]string{1: "A", 2: "B", 4: "C"},
}},
{`sub void s(E e) {
G = e
}
cmd void c(E e) {
s(A | B | C)
}`, &analysis.EnumValue{
Numbers: u64(0, 1, 2, 4),
Labels: map[uint64]string{1: "A", 2: "B", 4: "C"},
}},
Expand All @@ -185,18 +194,18 @@ func TestBitfieldParameterAnalysis(t *testing.T) {
expected *analysis.EnumValue
}{
{`cmd void c(E e) {
switch e {
case A, B, C: {}
}
}`, &analysis.EnumValue{
switch e {
case A, B, C: {}
}
}`, &analysis.EnumValue{
Numbers: anyU64,
Labels: map[uint64]string{1: "A", 2: "B", 4: "C"},
}},
{`cmd void c(E e) {
if (A in e) { }
if (B in e) { }
if (C in e) { }
}`, &analysis.EnumValue{
if (A in e) { }
if (B in e) { }
if (C in e) { }
}`, &analysis.EnumValue{
Numbers: anyU64,
Labels: map[uint64]string{1: "A", 2: "B", 4: "C"},
}},
Expand Down
22 changes: 17 additions & 5 deletions gapil/analysis/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,12 +475,14 @@ func (s *scope) valueOf(n semantic.Expression) (out Value, setter func(Value)) {
lhs, _ := s.valueOf(n.LHS)
rhs, _ := s.valueOf(n.RHS)
set := func(v Value) {
switch v.(*BoolValue).Possibility {
case True:
s.considerTrue(n)
if v, ok := v.(*BoolValue); ok {
switch v.Possibility {
case True:
s.considerTrue(n)

case False:
s.considerFalse(n)
case False:
s.considerFalse(n)
}
}
}

Expand Down Expand Up @@ -520,6 +522,16 @@ func (s *scope) valueOf(n semantic.Expression) (out Value, setter func(Value)) {
if r, ok := lhs.(*BoolValue); ok {
return r.Or(rhs.(*BoolValue)), set
}

case ast.OpBitwiseOr:
if r, ok := lhs.(*EnumValue); ok {
return r.Union(rhs.(*EnumValue)), set
}

case ast.OpBitwiseAnd:
if r, ok := lhs.(*EnumValue); ok {
return r.Intersect(rhs.(*EnumValue)), set
}
}

case *semantic.UnaryOp:
Expand Down

0 comments on commit 06f27fc

Please sign in to comment.