kconfig: remove tristate choice support

I previously submitted a fix for a bug in the choice feature [1], where
I mentioned, "Another (much cleaner) approach would be to remove the
tristate choice support entirely".

There are more issues in the tristate choice feature. For example, you
can observe a couple of bugs in the following test code.

[Test Code]

    config MODULES
            def_bool y
            modules

    choice
            prompt "tristate choice"
            default A

    config A
            tristate "A"

    config B
            tristate "B"

    endchoice

Bug 1: the 'default' property is not correctly processed

'make alldefconfig' produces:

    CONFIG_MODULES=y
    # CONFIG_A is not set
    # CONFIG_B is not set

However, the correct output should be:

    CONFIG_MODULES=y
    CONFIG_A=y
    # CONFIG_B is not set

The unit test file, scripts/kconfig/tests/choice/alldef_expected_config,
is wrong as well.

Bug 2: choice members never get 'y' with randconfig

For the test code above, the following combinations are possible:

               A    B
        (1)    y    n
        (2)    n    y
        (3)    m    m
        (4)    m    n
        (5)    n    m
        (6)    n    n

'make randconfig' never produces (1) or (2).

These bugs are fixable, but a more critical problem is the lack of a
sensible syntax to specify the default for the tristate choice.
The default for the choice must be one of the choice members, which
cannot specify any of the patterns (3) through (6) above.

In addition, I have never seen it being used in a useful way.

The following commits removed unnecessary use of tristate choices:

 - df8df5e4bc ("usb: get rid of 'choice' for legacy gadget drivers")
 - bfb57ef054 ("rapidio: remove choice for enumeration")

This commit removes the tristate choice support entirely, which allows
me to delete a lot of code, making further refactoring easier.

Note:
This includes the revert of commit fa64e5f6a3 ("kconfig/symbol.c:
handle choice_values that depend on 'm' symbols"). It was suspicious
because it did not address the root cause but introduced inconsistency
in visibility between choice members and other symbols.

[1]: https://lore.kernel.org/linux-kbuild/20240427104231.2728905-1-masahiroy@kernel.org/T/#m0a1bb6992581462ceca861b409bb33cb8fd7dbae

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Nicolas Schier <nicolas@fjasle.eu>
This commit is contained in:
Masahiro Yamada
2024-06-02 21:54:14 +09:00
parent 03638aaa79
commit fde192511b
28 changed files with 44 additions and 324 deletions

View File

@@ -114,21 +114,13 @@ static void set_randconfig_seed(void)
srand(seed);
}
static bool randomize_choice_values(struct symbol *csym)
static void randomize_choice_values(struct symbol *csym)
{
struct property *prop;
struct symbol *sym;
struct expr *e;
int cnt, def;
/*
* If choice is mod then we may have more items selected
* and if no then no-one.
* In both cases stop.
*/
if (csym->curr.tri != yes)
return false;
prop = sym_get_choice_prop(csym);
/* count entries in choice block */
@@ -157,8 +149,6 @@ static bool randomize_choice_values(struct symbol *csym)
csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */
csym->flags &= ~SYMBOL_VALID;
return true;
}
enum conf_def_mode {
@@ -269,15 +259,6 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
sym_clear_all_valid();
/*
* We have different type of choice blocks.
* If curr.tri equals to mod then we can select several
* choice symbols in one block.
* In this case we do nothing.
* If curr.tri equals yes then only one symbol can be
* selected in a choice block and we set it to yes,
* and the rest to no.
*/
if (mode != def_random) {
for_all_symbols(csym) {
if ((sym_is_choice(csym) && !sym_has_value(csym)) ||
@@ -292,11 +273,10 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
sym_calc_value(csym);
if (mode == def_random)
has_changed |= randomize_choice_values(csym);
else {
randomize_choice_values(csym);
else
set_all_choice_values(csym);
has_changed = true;
}
has_changed = true;
}
return has_changed;
@@ -454,27 +434,6 @@ static void conf_choice(struct menu *menu)
sym = menu->sym;
is_new = !sym_has_value(sym);
if (sym_is_changeable(sym)) {
conf_sym(menu);
sym_calc_value(sym);
switch (sym_get_tristate_value(sym)) {
case no:
case mod:
return;
case yes:
break;
}
} else {
switch (sym_get_tristate_value(sym)) {
case no:
return;
case mod:
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
return;
case yes:
break;
}
}
while (1) {
int cnt, def;
@@ -596,9 +555,7 @@ static void conf(struct menu *menu)
if (sym_is_choice(sym)) {
conf_choice(menu);
if (sym->curr.tri != mod)
return;
goto conf_childs;
return;
}
switch (sym->type) {
@@ -631,8 +588,7 @@ static void check_conf(struct menu *menu)
sym = menu->sym;
if (sym && !sym_has_value(sym) &&
(sym_is_changeable(sym) ||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes))) {
(sym_is_changeable(sym) || sym_is_choice(sym))) {
switch (input_mode) {
case listnewconfig: