Let kconfig exit with error on duplicated Kconfig file inclusion. Repeated inclusion of Kbuild files are considered bad-practise with regard to maintenance; and Kconfig language is rich enough that there should be no need for that. If repeated inclusion of Kconfig files is detected, error out with messages like: Kconfig.inc1:4: error: repeated inclusion of Kconfig.inc3 Kconfig.inc2:3: note: location of first inclusion of Kconfig.inc3 While commit f094f8a1b273 ("kconfig: allow multiple inclusion of the same file") introduced detection of recursive inclusions of Kconfig files, it explicitly allowed repeated inclusions, unfortunately w/o reasoning.
Unified · Split
| @@ -402,7 +402,7 @@ void zconf_initscan(const char *name) · 401 unmodified lines | ||
| 402 | 402 | exit(1); |
| 403 | 403 | } |
| 404 | 404 | |
| 405 | − cur_filename = file_lookup(name); | |
| 405 | + cur_filename = file_lookup(name, NULL, 0); | |
| 406 | 406 | yylineno = 1; |
| 407 | 407 | } |
| 408 | 408 | |
| @@ -443,7 +443,7 @@ void zconf_nextfile(const char *name) · 34 unmodified lines | ||
| 443 | 443 | } |
| 444 | 444 | |
| 445 | 445 | yylineno = 1; |
| 446 | − cur_filename = file_lookup(name); | |
| 446 | + cur_filename = file_lookup(name, cur_filename, cur_lineno); | |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | 449 | static void zconf_endfile(void) |
| @@ -51,7 +51,8 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) · 50 unmodified lines | ||
| 51 | 51 | } |
| 52 | 52 | |
| 53 | 53 | /* util.c */ |
| 54 | −const char *file_lookup(const char *name); | |
| 54 | +const char *file_lookup(const char *name, | |
| 55 | + const char *parent_name, int parent_lineno); | |
| 55 | 56 | |
| 56 | 57 | /* lexer.l */ |
| 57 | 58 | int yylex(void); |
| @@ -0,0 +1,3 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only | |
| 2 | + | |
| 3 | +source "Kconfig.inc1" | |
| @@ -0,0 +1,4 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only | |
| 2 | + | |
| 3 | +source "Kconfig.inc2" | |
| 4 | +source "Kconfig.inc3" | |
| @@ -0,0 +1,3 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only | |
| 2 | + | |
| 3 | +source "Kconfig.inc3" | |
| @@ -0,0 +1 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only | |
| @@ -0,0 +1,10 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0 | |
| 2 | +""" | |
| 3 | +Detect repeated inclusion error. | |
| 4 | + | |
| 5 | +If repeated inclusion is detected, it should fail with error message. | |
| 6 | +""" | |
| 7 | + | |
| 8 | +def test(conf): | |
| 9 | + assert conf.oldaskconfig() != 0 | |
| 10 | + assert conf.stderr_contains('expected_stderr') | |
| @@ -0,0 +1,2 @@ | ||
| 1 | +Kconfig.inc1:4: error: Repeated inclusion of Kconfig.inc3 | |
| 2 | +Kconfig.inc2:3: note: Location of first inclusion of Kconfig.inc3 | |
| @@ -18,25 +18,50 @@ static HASHTABLE_DEFINE(file_hashtable, 1U << 11); · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | struct file { |
| 20 | 20 | struct hlist_node node; |
| 21 | + struct { | |
| 22 | + const char *name; | |
| 23 | + int lineno; | |
| 24 | + } parent; | |
| 21 | 25 | char name[]; |
| 22 | 26 | }; |
| 23 | 27 | |
| 28 | +static void die_duplicated_include(struct file *file, | |
| 29 | + const char *parent, int lineno) | |
| 30 | +{ | |
| 31 | + fprintf(stderr, | |
| 32 | + "%s:%d: error: repeated inclusion of %s\n" | |
| 33 | + "%s:%d: note: location of first inclusion of %s\n", | |
| 34 | + parent, lineno, file->name, | |
| 35 | + file->parent.name, file->parent.lineno, file->name); | |
| 36 | + exit(1); | |
| 37 | +} | |
| 38 | + | |
| 24 | 39 | /* file already present in list? If not add it */ |
| 25 | −const char *file_lookup(const char *name) | |
| 40 | +const char *file_lookup(const char *name, | |
| 41 | + const char *parent_name, int parent_lineno) | |
| 26 | 42 | { |
| 43 | + const char *parent = NULL; | |
| 27 | 44 | struct file *file; |
| 28 | 45 | size_t len; |
| 29 | 46 | int hash = hash_str(name); |
| 30 | 47 | |
| 48 | + if (parent_name) | |
| 49 | + parent = file_lookup(parent_name, NULL, 0); | |
| 50 | + | |
| 31 | 51 | hash_for_each_possible(file_hashtable, file, node, hash) |
| 32 | − if (!strcmp(name, file->name)) | |
| 33 | − return file->name; | |
| 52 | + if (!strcmp(name, file->name)) { | |
| 53 | + if (!parent_name) | |
| 54 | + return file->name; | |
| 55 | + die_duplicated_include(file, parent, parent_lineno); | |
| 56 | + } | |
| 34 | 57 | |
| 35 | 58 | len = strlen(name); |
| 36 | 59 | file = xmalloc(sizeof(*file) + len + 1); |
| 37 | 60 | memset(file, 0, sizeof(*file)); |
| 38 | 61 | memcpy(file->name, name, len); |
| 39 | 62 | file->name[len] = '\0'; |
| 63 | + file->parent.name = parent; | |
| 64 | + file->parent.lineno = parent_lineno; | |
| 40 | 65 | |
| 41 | 66 | hash_add(file_hashtable, &file->node, hash); |
| 42 | 67 | |