mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
			
			
This commit is contained in:
		
							parent
							
								
									9a88b338d6
								
							
						
					
					
						commit
						7e3465f63a
					
				
					 4 changed files with 18 additions and 13 deletions
				
			
		| 
						 | 
					@ -552,11 +552,6 @@ static int conf_choice(struct menu *menu)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		sym_set_tristate_value(child->sym, yes);
 | 
							sym_set_tristate_value(child->sym, yes);
 | 
				
			||||||
		for (child = child->list; child; child = child->next) {
 | 
					 | 
				
			||||||
			indent += 2;
 | 
					 | 
				
			||||||
			conf(child);
 | 
					 | 
				
			||||||
			indent -= 2;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,7 +89,7 @@ void menu_add_visibility(struct expr *dep);
 | 
				
			||||||
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
 | 
					struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
 | 
				
			||||||
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
 | 
					void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
 | 
				
			||||||
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
 | 
					void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
 | 
				
			||||||
void menu_finalize(struct menu *parent);
 | 
					void menu_finalize(void);
 | 
				
			||||||
void menu_set_type(int type);
 | 
					void menu_set_type(int type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct menu rootmenu;
 | 
					extern struct menu rootmenu;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -282,7 +282,7 @@ static void sym_check_prop(struct symbol *sym)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void menu_finalize(struct menu *parent)
 | 
					static void _menu_finalize(struct menu *parent, bool inside_choice)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct menu *menu, *last_menu;
 | 
						struct menu *menu, *last_menu;
 | 
				
			||||||
	struct symbol *sym;
 | 
						struct symbol *sym;
 | 
				
			||||||
| 
						 | 
					@ -296,7 +296,12 @@ void menu_finalize(struct menu *parent)
 | 
				
			||||||
		 * and propagate parent dependencies before moving on.
 | 
							 * and propagate parent dependencies before moving on.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sym && sym_is_choice(sym)) {
 | 
							bool is_choice = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (sym && sym_is_choice(sym))
 | 
				
			||||||
 | 
								is_choice = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (is_choice) {
 | 
				
			||||||
			if (sym->type == S_UNKNOWN) {
 | 
								if (sym->type == S_UNKNOWN) {
 | 
				
			||||||
				/* find the first choice value to find out choice type */
 | 
									/* find the first choice value to find out choice type */
 | 
				
			||||||
				current_entry = parent;
 | 
									current_entry = parent;
 | 
				
			||||||
| 
						 | 
					@ -394,7 +399,7 @@ void menu_finalize(struct menu *parent)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sym && sym_is_choice(sym))
 | 
							if (is_choice)
 | 
				
			||||||
			expr_free(parentdep);
 | 
								expr_free(parentdep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
| 
						 | 
					@ -402,8 +407,8 @@ void menu_finalize(struct menu *parent)
 | 
				
			||||||
		 * moving on
 | 
							 * moving on
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		for (menu = parent->list; menu; menu = menu->next)
 | 
							for (menu = parent->list; menu; menu = menu->next)
 | 
				
			||||||
			menu_finalize(menu);
 | 
								_menu_finalize(menu, is_choice);
 | 
				
			||||||
	} else if (sym) {
 | 
						} else if (!inside_choice && sym) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Automatic submenu creation. If sym is a symbol and A, B, C,
 | 
							 * Automatic submenu creation. If sym is a symbol and A, B, C,
 | 
				
			||||||
		 * ... are consecutive items (symbols, menus, ifs, etc.) that
 | 
							 * ... are consecutive items (symbols, menus, ifs, etc.) that
 | 
				
			||||||
| 
						 | 
					@ -463,7 +468,7 @@ void menu_finalize(struct menu *parent)
 | 
				
			||||||
			/* Superset, put in submenu */
 | 
								/* Superset, put in submenu */
 | 
				
			||||||
			expr_free(dep2);
 | 
								expr_free(dep2);
 | 
				
			||||||
		next:
 | 
							next:
 | 
				
			||||||
			menu_finalize(menu);
 | 
								_menu_finalize(menu, false);
 | 
				
			||||||
			menu->parent = parent;
 | 
								menu->parent = parent;
 | 
				
			||||||
			last_menu = menu;
 | 
								last_menu = menu;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -582,6 +587,11 @@ void menu_finalize(struct menu *parent)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void menu_finalize(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						_menu_finalize(&rootmenu, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool menu_has_prompt(struct menu *menu)
 | 
					bool menu_has_prompt(struct menu *menu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!menu->prompt)
 | 
						if (!menu->prompt)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -515,7 +515,7 @@ void conf_parse(const char *name)
 | 
				
			||||||
		menu_add_prompt(P_MENU, "Main menu", NULL);
 | 
							menu_add_prompt(P_MENU, "Main menu", NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	menu_finalize(&rootmenu);
 | 
						menu_finalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	menu = &rootmenu;
 | 
						menu = &rootmenu;
 | 
				
			||||||
	while (menu) {
 | 
						while (menu) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue