kconfig: report recursive dependency involving 'imply'
authorMasahiro Yamada <yamada.masahiro@socionext.com>
Wed, 15 Aug 2018 05:59:44 +0000 (14:59 +0900)
committerChristian Lamparter <chunkeey@gmail.com>
Sun, 10 Feb 2019 21:27:12 +0000 (22:27 +0100)
Currently, Kconfig does not complain about the recursive dependency
where 'imply' keywords are involved.

[Test Code]

  config A
          bool "a"

  config B
          bool "b"
          imply A
          depends on A

In the code above, Kconfig cannot calculate the symbol values correctly
due to the circular dependency.  For example, allyesconfig followed by
syncconfig results in an odd behavior because CONFIG_B becomes visible
in syncconfig.

  $ make allyesconfig
  scripts/kconfig/conf  --allyesconfig Kconfig
  #
  # configuration written to .config
  #
  $ cat .config
  #
  # Automatically generated file; DO NOT EDIT.
  # Main menu
  #
  CONFIG_A=y
  $ make syncconfig
  scripts/kconfig/conf  --syncconfig Kconfig
  *
  * Restart config...
  *
  *
  * Main menu
  *
  a (A) [Y/n/?] y
    b (B) [N/y/?] (NEW)

To detect this correctly, sym_check_expr_deps() should recurse to
not only sym->rev_dep.expr but also sym->implied.expr .

At this moment, sym_check_print_recursive() cannot distinguish
'select' and 'imply' since it does not know the precise context
where the recursive dependency has been hit.  This will be solved
by the next commit.

In fact, even the document and the unit-test are confused.  Using
'imply' does not solve recursive dependency since 'imply' addresses
the unmet direct dependency, which 'select' could cause.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Tested-by: Dirk Gouders <dirk@gouders.net>
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
config/symbol.c

index 688f487ff454e629eb9b83dc7c489c56da38cdc0..90e706096af8221d23a26be37d83678dcfddfe36 100644 (file)
@@ -1098,7 +1098,7 @@ static void sym_check_print_recursive(struct symbol *last_sym)
                                sym->name ? sym->name : "<choice>",
                                next_sym->name ? next_sym->name : "<choice>");
                } else {
-                       fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
+                       fprintf(stderr, "%s:%d:\tsymbol %s is selected or implied by %s\n",
                                prop->file->name, prop->lineno,
                                sym->name ? sym->name : "<choice>",
                                next_sym->name ? next_sym->name : "<choice>");
@@ -1161,8 +1161,13 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
        if (sym2)
                goto out;
 
+       sym2 = sym_check_expr_deps(sym->implied.expr);
+       if (sym2)
+               goto out;
+
        for (prop = sym->prop; prop; prop = prop->next) {
-               if (prop->type == P_CHOICE || prop->type == P_SELECT)
+               if (prop->type == P_CHOICE || prop->type == P_SELECT ||
+                   prop->type == P_IMPLY)
                        continue;
                stack.prop = prop;
                sym2 = sym_check_expr_deps(prop->visible.expr);