Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 7e3465f

Browse files
committed
kconfig: do not reparent the menu inside a choice block
The boolean 'choice' is used to list exclusively selected config options. You must not add a dependency between choice members, because such a dependency would create an invisible entry. In the following test case, it is impossible to choose 'C'. [Test Case 1] choice prompt "Choose one, but how to choose C?" config A bool "A" config B bool "B" config C bool "C" depends on A endchoice Hence, Kconfig shows the following error message: Kconfig:1:error: recursive dependency detected! Kconfig:1: choice <choice> contains symbol C Kconfig:10: symbol C is part of choice A Kconfig:4: symbol A is part of choice <choice> For a resolution refer to Documentation/kbuild/kconfig-language.rst subsection "Kconfig recursive dependency limitations" However, Kconfig does not report anything for the following similar code: [Test Case 2] choice prompt "Choose one, but how to choose B?" config A bool "A" config B bool "B" depends on A config C bool "C" endchoice This is because menu_finalize() reparents the menu tree when an entry depends on the preceding one. With reparenting, the menu tree: choice |- A |- B \- C ... will be transformed into the following structure: choice |- A | \- B \- C Consequently, Kconfig considers only 'A' and 'C' as choice members. This behavior is awkward. The second test case should be an error too. This commit stops reparenting inside a choice. Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
1 parent 9a88b33 commit 7e3465f

File tree

4 files changed

+18
-13
lines changed

4 files changed

+18
-13
lines changed

scripts/kconfig/conf.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -552,11 +552,6 @@ static int conf_choice(struct menu *menu)
552552
continue;
553553
}
554554
sym_set_tristate_value(child->sym, yes);
555-
for (child = child->list; child; child = child->next) {
556-
indent += 2;
557-
conf(child);
558-
indent -= 2;
559-
}
560555
return 1;
561556
}
562557
}

scripts/kconfig/lkc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void menu_add_visibility(struct expr *dep);
8989
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
9090
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
9191
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
92-
void menu_finalize(struct menu *parent);
92+
void menu_finalize(void);
9393
void menu_set_type(int type);
9494

9595
extern struct menu rootmenu;

scripts/kconfig/menu.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ static void sym_check_prop(struct symbol *sym)
282282
}
283283
}
284284

285-
void menu_finalize(struct menu *parent)
285+
static void _menu_finalize(struct menu *parent, bool inside_choice)
286286
{
287287
struct menu *menu, *last_menu;
288288
struct symbol *sym;
@@ -296,7 +296,12 @@ void menu_finalize(struct menu *parent)
296296
* and propagate parent dependencies before moving on.
297297
*/
298298

299-
if (sym && sym_is_choice(sym)) {
299+
bool is_choice = false;
300+
301+
if (sym && sym_is_choice(sym))
302+
is_choice = true;
303+
304+
if (is_choice) {
300305
if (sym->type == S_UNKNOWN) {
301306
/* find the first choice value to find out choice type */
302307
current_entry = parent;
@@ -394,16 +399,16 @@ void menu_finalize(struct menu *parent)
394399
}
395400
}
396401

397-
if (sym && sym_is_choice(sym))
402+
if (is_choice)
398403
expr_free(parentdep);
399404

400405
/*
401406
* Recursively process children in the same fashion before
402407
* moving on
403408
*/
404409
for (menu = parent->list; menu; menu = menu->next)
405-
menu_finalize(menu);
406-
} else if (sym) {
410+
_menu_finalize(menu, is_choice);
411+
} else if (!inside_choice && sym) {
407412
/*
408413
* Automatic submenu creation. If sym is a symbol and A, B, C,
409414
* ... are consecutive items (symbols, menus, ifs, etc.) that
@@ -463,7 +468,7 @@ void menu_finalize(struct menu *parent)
463468
/* Superset, put in submenu */
464469
expr_free(dep2);
465470
next:
466-
menu_finalize(menu);
471+
_menu_finalize(menu, false);
467472
menu->parent = parent;
468473
last_menu = menu;
469474
}
@@ -582,6 +587,11 @@ void menu_finalize(struct menu *parent)
582587
}
583588
}
584589

590+
void menu_finalize(void)
591+
{
592+
_menu_finalize(&rootmenu, false);
593+
}
594+
585595
bool menu_has_prompt(struct menu *menu)
586596
{
587597
if (!menu->prompt)

scripts/kconfig/parser.y

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ void conf_parse(const char *name)
515515
menu_add_prompt(P_MENU, "Main menu", NULL);
516516
}
517517

518-
menu_finalize(&rootmenu);
518+
menu_finalize();
519519

520520
menu = &rootmenu;
521521
while (menu) {

0 commit comments

Comments
 (0)