kconfig: fix choice dependency check
Properly check the dependency of choices as a group. Also fix that sym_check_deps() correctly terminates the dependency loop error check (otherwise it would continue printing the dependency chain). Signed-off-by: Roman Zippel <zippel@linux-m68k.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
This commit is contained in:
parent
dfecbec8b5
commit
4898117886
|
@ -762,8 +762,6 @@ struct symbol **sym_re_search(const char *pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct symbol *sym_check_deps(struct symbol *sym);
|
|
||||||
|
|
||||||
static struct symbol *sym_check_expr_deps(struct expr *e)
|
static struct symbol *sym_check_expr_deps(struct expr *e)
|
||||||
{
|
{
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
@ -795,6 +793,65 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return NULL when dependencies are OK */
|
/* return NULL when dependencies are OK */
|
||||||
|
static struct symbol *sym_check_sym_deps(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct symbol *sym2;
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
|
||||||
|
if (sym2)
|
||||||
|
return sym2;
|
||||||
|
|
||||||
|
for (prop = sym->prop; prop; prop = prop->next) {
|
||||||
|
if (prop->type == P_CHOICE || prop->type == P_SELECT)
|
||||||
|
continue;
|
||||||
|
sym2 = sym_check_expr_deps(prop->visible.expr);
|
||||||
|
if (sym2)
|
||||||
|
break;
|
||||||
|
if (prop->type != P_DEFAULT || sym_is_choice(sym))
|
||||||
|
continue;
|
||||||
|
sym2 = sym_check_expr_deps(prop->expr);
|
||||||
|
if (sym2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sym2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct symbol *sym_check_choice_deps(struct symbol *choice)
|
||||||
|
{
|
||||||
|
struct symbol *sym, *sym2;
|
||||||
|
struct property *prop;
|
||||||
|
struct expr *e;
|
||||||
|
|
||||||
|
prop = sym_get_choice_prop(choice);
|
||||||
|
expr_list_for_each_sym(prop->expr, e, sym)
|
||||||
|
sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
|
||||||
|
|
||||||
|
choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
|
||||||
|
sym2 = sym_check_sym_deps(choice);
|
||||||
|
choice->flags &= ~SYMBOL_CHECK;
|
||||||
|
if (sym2)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
expr_list_for_each_sym(prop->expr, e, sym) {
|
||||||
|
sym2 = sym_check_sym_deps(sym);
|
||||||
|
if (sym2) {
|
||||||
|
fprintf(stderr, " -> %s", sym->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
expr_list_for_each_sym(prop->expr, e, sym)
|
||||||
|
sym->flags &= ~SYMBOL_CHECK;
|
||||||
|
|
||||||
|
if (sym2 && sym_is_choice_value(sym2) &&
|
||||||
|
prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
|
||||||
|
sym2 = choice;
|
||||||
|
|
||||||
|
return sym2;
|
||||||
|
}
|
||||||
|
|
||||||
struct symbol *sym_check_deps(struct symbol *sym)
|
struct symbol *sym_check_deps(struct symbol *sym)
|
||||||
{
|
{
|
||||||
struct symbol *sym2;
|
struct symbol *sym2;
|
||||||
|
@ -802,33 +859,34 @@ struct symbol *sym_check_deps(struct symbol *sym)
|
||||||
|
|
||||||
if (sym->flags & SYMBOL_CHECK) {
|
if (sym->flags & SYMBOL_CHECK) {
|
||||||
fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
|
fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
|
||||||
sym->prop->file->name, sym->prop->lineno, sym->name);
|
sym->prop->file->name, sym->prop->lineno,
|
||||||
|
sym->name ? sym->name : "<choice>");
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
if (sym->flags & SYMBOL_CHECKED)
|
if (sym->flags & SYMBOL_CHECKED)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
|
if (sym_is_choice_value(sym)) {
|
||||||
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
|
/* for choice groups start the check with main choice symbol */
|
||||||
if (sym2)
|
prop = sym_get_choice_prop(sym);
|
||||||
goto out;
|
sym2 = sym_check_deps(prop_get_symbol(prop));
|
||||||
|
} else if (sym_is_choice(sym)) {
|
||||||
for (prop = sym->prop; prop; prop = prop->next) {
|
sym2 = sym_check_choice_deps(sym);
|
||||||
if (prop->type == P_CHOICE || prop->type == P_SELECT)
|
} else {
|
||||||
continue;
|
sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
|
||||||
sym2 = sym_check_expr_deps(prop->visible.expr);
|
sym2 = sym_check_sym_deps(sym);
|
||||||
if (sym2)
|
sym->flags &= ~SYMBOL_CHECK;
|
||||||
goto out;
|
|
||||||
if (prop->type != P_DEFAULT || sym_is_choice(sym))
|
|
||||||
continue;
|
|
||||||
sym2 = sym_check_expr_deps(prop->expr);
|
|
||||||
if (sym2)
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
if (sym2)
|
if (sym2) {
|
||||||
fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": "");
|
fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
|
||||||
sym->flags &= ~SYMBOL_CHECK;
|
if (sym2 == sym) {
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
zconfnerrs++;
|
||||||
|
sym2 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return sym2;
|
return sym2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue