Skip to content

Commit d533828

Browse files
committed
kconfig: fix conditional prompt behavior for choice
When a prompt is followed by "if <expr>", the symbol is configurable when the if-conditional evaluates to true. A typical usage is as follows: menuconfig BLOCK bool "Enable the block layer" if EXPERT default y When EXPERT=n, the prompt is hidden, but this config entry is still active, and BLOCK is set to its default value 'y'. When EXPERT=y, the prompt is shown, making BLOCK a user-configurable option. This usage is common throughout the kernel tree, but it has never worked within a choice block. [Test Code] config EXPERT bool "Allow expert users to modify more options" choice prompt "Choose" if EXPERT config A bool "A" config B bool "B" endchoice [Result] # CONFIG_EXPERT is not set When the prompt is hidden, the choice block should produce the default without asking for the user's preference. Hence, the output should be: # CONFIG_EXPERT is not set CONFIG_A=y # CONFIG_B is not set Removing unnecessary hacks fixes the issue. This commit also changes the behavior of 'select' by choice members. [Test Code 2] config MODULES def_bool y modules config DEP def_tristate m if DEP choice prompt "choose" config A bool "A" select C endchoice config B def_bool y select D endif config C tristate config D tristate The current output is as follows: CONFIG_MODULES=y CONFIG_DEP=m CONFIG_A=y CONFIG_B=y CONFIG_C=y CONFIG_D=m With this commit, the output will be changed as follows: CONFIG_MODULES=y CONFIG_DEP=m CONFIG_A=y CONFIG_B=y CONFIG_C=m CONFIG_D=m CONFIG_C will be changed to 'm' because 'select C' will inherit the dependency on DEP, which is 'm'. This change is aligned with the behavior of 'select' outside a choice block; 'select D' depends on DEP, therefore D is selected by (B && DEP). Note: With this commit, allmodconfig will set CONFIG_USB_ROLE_SWITCH to 'm' instead of 'y'. I did not see any build regression with this change. Signed-off-by: Masahiro Yamada <[email protected]>
1 parent b9d7321 commit d533828

File tree

2 files changed

+4
-36
lines changed

2 files changed

+4
-36
lines changed

scripts/kconfig/menu.c

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
306306
struct menu *menu, *last_menu;
307307
struct symbol *sym;
308308
struct property *prop;
309-
struct expr *parentdep, *basedep, *dep, *dep2;
309+
struct expr *basedep, *dep, *dep2;
310310

311311
sym = parent->sym;
312312
if (parent->list) {
@@ -315,24 +315,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
315315
* and propagate parent dependencies before moving on.
316316
*/
317317

318-
bool is_choice = false;
319-
320-
if (sym && sym_is_choice(sym))
321-
is_choice = true;
322-
323-
if (is_choice) {
324-
/*
325-
* Use the choice itself as the parent dependency of
326-
* the contained items. This turns the mode of the
327-
* choice into an upper bound on the visibility of the
328-
* choice value symbols.
329-
*/
330-
parentdep = expr_alloc_symbol(sym);
331-
} else {
332-
/* Menu node for 'menu', 'if' */
333-
parentdep = parent->dep;
334-
}
335-
336318
/* For each child menu node... */
337319
for (menu = parent->list; menu; menu = menu->next) {
338320
/*
@@ -341,7 +323,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
341323
*/
342324
basedep = rewrite_m(menu->dep);
343325
basedep = expr_transform(basedep);
344-
basedep = expr_alloc_and(expr_copy(parentdep), basedep);
326+
basedep = expr_alloc_and(expr_copy(parent->dep), basedep);
345327
basedep = expr_eliminate_dups(basedep);
346328
menu->dep = basedep;
347329

@@ -405,15 +387,12 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
405387
}
406388
}
407389

408-
if (is_choice)
409-
expr_free(parentdep);
410-
411390
/*
412391
* Recursively process children in the same fashion before
413392
* moving on
414393
*/
415394
for (menu = parent->list; menu; menu = menu->next)
416-
_menu_finalize(menu, is_choice);
395+
_menu_finalize(menu, sym && sym_is_choice(sym));
417396
} else if (!inside_choice && sym) {
418397
/*
419398
* Automatic submenu creation. If sym is a symbol and A, B, C,
@@ -541,17 +520,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
541520
sym_check_prop(sym);
542521
sym->flags |= SYMBOL_WARNED;
543522
}
544-
545-
/*
546-
* For choices, add a reverse dependency (corresponding to a select) of
547-
* '<visibility> && y'. This prevents the user from setting the choice
548-
* mode to 'n' when the choice is visible.
549-
*/
550-
if (sym && sym_is_choice(sym) && parent->prompt) {
551-
sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
552-
expr_alloc_and(parent->prompt->visible.expr,
553-
expr_alloc_symbol(&symbol_yes)));
554-
}
555523
}
556524

557525
void menu_finalize(void)

scripts/kconfig/symbol.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ const char *sym_get_string_value(struct symbol *sym)
868868

869869
bool sym_is_changeable(struct symbol *sym)
870870
{
871-
return sym->visible > sym->rev_dep.tri;
871+
return !sym_is_choice(sym) && sym->visible > sym->rev_dep.tri;
872872
}
873873

874874
HASHTABLE_DEFINE(sym_hashtable, SYMBOL_HASHSIZE);

0 commit comments

Comments
 (0)