From 781340bec8eda54d9d8edbd09dde6f7454911ce4 Mon Sep 17 00:00:00 2001 From: Paul Chaignon Date: Fri, 1 Dec 2023 13:09:24 +0100 Subject: compiler: error on circular dependencies in flag definitions To detect those circular dependencies, we simply keep track of which flags we already visited when flattening the flags definition. Suggested-by: Aleksandr Nogikh Signed-off-by: Paul Chaignon --- pkg/compiler/compiler.go | 13 ++++++++++--- pkg/compiler/testdata/errors.txt | 6 ++++++ 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'pkg/compiler') diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index 3c5dea1d1..2e13988b7 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -361,7 +361,7 @@ func arrayContains(a []string, v string) bool { func (comp *compiler) flattenFlags() { for name, flags := range comp.intFlags { - if err := comp.recurFlattenFlags(name, flags); err != nil { + if err := comp.recurFlattenFlags(name, flags, map[string]bool{}); err != nil { comp.error(flags.Pos, "%v", err) } } @@ -379,11 +379,18 @@ func (comp *compiler) flattenFlags() { } } -func (comp *compiler) recurFlattenFlags(name string, flags *ast.IntFlags) error { +func (comp *compiler) recurFlattenFlags(name string, flags *ast.IntFlags, visitedFlags map[string]bool) error { + if _, visited := visitedFlags[name]; visited { + return fmt.Errorf("flags %v used twice or circular dependency on %v", name, name) + } + visitedFlags[name] = true + var values []*ast.Int for _, flag := range flags.Values { if f, isFlags := comp.intFlags[flag.Ident]; isFlags { - comp.recurFlattenFlags(flag.Ident, f) + if err := comp.recurFlattenFlags(flag.Ident, f, visitedFlags); err != nil { + return err + } values = append(values, comp.intFlags[flag.Ident].Values...) } else { values = append(values, flag) diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt index 321ff8daf..47d343e36 100644 --- a/pkg/compiler/testdata/errors.txt +++ b/pkg/compiler/testdata/errors.txt @@ -97,6 +97,12 @@ f3000 = 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, nested_flags(a flags[f1000], b flags[f1100]) +f110 = 1, 2, 3, 4, f120 ### flags f110 used twice or circular dependency on f110 +f120 = 10, 11, 12, f130 ### flags f120 used twice or circular dependency on f120 +f130 = 100, 110, f110 ### flags f130 used twice or circular dependency on f130 + +loop_flags(a flags[f110]) + resource r2[r0]: 2 resource r3[int32:1] ### unexpected ':', only struct fields can be bitfields resource r4[int32[opt]] ### resource base can't be marked as opt -- cgit mrf-deployment