Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <masahiroy@kernel.org>

+4 -36
+3 -35
scripts/kconfig/menu.c
··· 306 306 struct menu *menu, *last_menu; 307 307 struct symbol *sym; 308 308 struct property *prop; 309 - struct expr *parentdep, *basedep, *dep, *dep2; 309 + struct expr *basedep, *dep, *dep2; 310 310 311 311 sym = parent->sym; 312 312 if (parent->list) { ··· 314 314 * This menu node has children. We (recursively) process them 315 315 * and propagate parent dependencies before moving on. 316 316 */ 317 - 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 317 336 318 /* For each child menu node... */ 337 319 for (menu = parent->list; menu; menu = menu->next) { ··· 323 341 */ 324 342 basedep = rewrite_m(menu->dep); 325 343 basedep = expr_transform(basedep); 326 - basedep = expr_alloc_and(expr_copy(parentdep), basedep); 344 + basedep = expr_alloc_and(expr_copy(parent->dep), basedep); 327 345 basedep = expr_eliminate_dups(basedep); 328 346 menu->dep = basedep; 329 347 ··· 387 405 } 388 406 } 389 407 390 - if (is_choice) 391 - expr_free(parentdep); 392 - 393 408 /* 394 409 * Recursively process children in the same fashion before 395 410 * moving on 396 411 */ 397 412 for (menu = parent->list; menu; menu = menu->next) 398 - _menu_finalize(menu, is_choice); 413 + _menu_finalize(menu, sym && sym_is_choice(sym)); 399 414 } else if (!inside_choice && sym) { 400 415 /* 401 416 * Automatic submenu creation. If sym is a symbol and A, B, C, ··· 519 540 /* Check properties connected to this symbol */ 520 541 sym_check_prop(sym); 521 542 sym->flags |= SYMBOL_WARNED; 522 - } 523 - 524 - /* 525 - * For choices, add a reverse dependency (corresponding to a select) of 526 - * '<visibility> && y'. This prevents the user from setting the choice 527 - * mode to 'n' when the choice is visible. 528 - */ 529 - if (sym && sym_is_choice(sym) && parent->prompt) { 530 - sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, 531 - expr_alloc_and(parent->prompt->visible.expr, 532 - expr_alloc_symbol(&symbol_yes))); 533 543 } 534 544 } 535 545
+1 -1
scripts/kconfig/symbol.c
··· 868 868 869 869 bool sym_is_changeable(struct symbol *sym) 870 870 { 871 - return sym->visible > sym->rev_dep.tri; 871 + return !sym_is_choice(sym) && sym->visible > sym->rev_dep.tri; 872 872 } 873 873 874 874 HASHTABLE_DEFINE(sym_hashtable, SYMBOL_HASHSIZE);