diff --git a/.github/workflows/coding_guidelines.yml b/.github/workflows/coding_guidelines.yml new file mode 100644 index 0000000000000..052334b461b9f --- /dev/null +++ b/.github/workflows/coding_guidelines.yml @@ -0,0 +1,52 @@ +name: Coding Guidelines + +on: pull_request_target + +jobs: + compliance_job: + runs-on: ubuntu-latest + name: Run coding guidelines checks on patch series (PR) + steps: + - name: Checkout the code + uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: cache-pip + uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-doc-pip + + - name: Install python dependencies + run: | + pip3 install unidiff + pip3 install wheel + pip3 install sh + + - name: Install Packages + run: | + sudo apt-get install ocaml-base-nox + wget https://launchpad.net/~npalix/+archive/ubuntu/coccinelle/+files/coccinelle_1.0.8~20.04npalix1_amd64.deb + sudo dpkg -i coccinelle_1.0.8~20.04npalix1_amd64.deb + + - name: Run Coding Guildeines Checks + continue-on-error: true + id: coding_guidelines + env: + BASE_REF: ${{ github.base_ref }} + run: | + export ZEPHYR_BASE=$PWD + source zephyr-env.sh + # debug + ls -la + git log --pretty=oneline | head -n 10 + ./scripts/ci/guideline_check.py --output output.txt -c origin/${BASE_REF}.. + + - name: Annotate + uses: yuzutech/annotations-action@v0.3.0 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + input: './violations.json' + title: 'Violations' diff --git a/drivers/i2c/i2c_imx.c b/drivers/i2c/i2c_imx.c index f52631bec5d31..edcf31992c882 100644 --- a/drivers/i2c/i2c_imx.c +++ b/drivers/i2c/i2c_imx.c @@ -26,7 +26,7 @@ LOG_MODULE_REGISTER(i2c_imx); struct i2c_imx_config { I2C_Type *base; - void (*irq_config_func)(const struct device *dev); + void (*irq_config_func)(const struct device *device); uint32_t bitrate; }; diff --git a/kernel/sem.c b/kernel/sem.c index 78e93adb62c02..dbb134bbb5f3a 100644 --- a/kernel/sem.c +++ b/kernel/sem.c @@ -48,6 +48,7 @@ struct k_sem *_trace_list_k_sem; static int init_sem_module(const struct device *dev) { ARG_UNUSED(dev); + int exp; Z_STRUCT_SECTION_FOREACH(k_sem, sem) { SYS_TRACING_OBJ_INIT(k_sem, sem); diff --git a/lib/os/heap.c b/lib/os/heap.c index 363427a3e58f4..10777c48daa57 100644 --- a/lib/os/heap.c +++ b/lib/os/heap.c @@ -21,6 +21,7 @@ static void *chunk_mem(struct z_heap *h, chunkid_t c) static void free_list_remove_bidx(struct z_heap *h, chunkid_t c, int bidx) { struct z_heap_bucket *b = &h->buckets[bidx]; + int remove; CHECK(!chunk_used(h, c)); CHECK(b->next != 0); diff --git a/scripts/ci/guideline_check.py b/scripts/ci/guideline_check.py new file mode 100755 index 0000000000000..3800199a7978f --- /dev/null +++ b/scripts/ci/guideline_check.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2021 Intel Corporation + +import os +import sh +import argparse +import re +from unidiff import PatchSet +import json + +if "ZEPHYR_BASE" not in os.environ: + exit("$ZEPHYR_BASE environment variable undefined.") + +repository_path = os.environ['ZEPHYR_BASE'] + +sh_special_args = { + '_tty_out': False, + '_cwd': repository_path +} + +coccinelle_scripts = ["/scripts/coccinelle/reserved_names.cocci", + "/scripts/coccinelle/same_identifier.cocci", + "/scripts/coccinelle/identifier_length.cocci", + ] + + +def parse_coccinelle(contents: str, violations: dict): + reg = re.compile("([a-zA-Z0-9/]*\\.[ch]:[0-9]*)(:[0-9\\-]*: )(.*)") + for line in contents.split("\n"): + r = reg.match(line) + if r: + f = r.group(1) + if f in violations: + violations[f].append(r.group(3)) + else: + violations[r.group(1)] = [r.group(3)] + + +def parse_args(): + parser = argparse.ArgumentParser( + description="Check if change requires full twister") + parser.add_argument('-c', '--commits', default=None, + help="Commit range in the form: a..b") + parser.add_argument("-o", "--output", required=False, + help="Print violation into a file") + return parser.parse_args() + + +def main(): + args = parse_args() + if not args.commits: + exit("missing commit range") + + # pylint does not like the 'sh' library + # pylint: disable=too-many-function-args,unexpected-keyword-arg + commit = sh.git("diff", args.commits, **sh_special_args) + patch_set = PatchSet(commit) + zephyr_base = os.getenv("ZEPHYR_BASE") + violations = {} + numViolations = 0 + vlist = [] + + for f in patch_set: + if not f.path.endswith(".c") and not f.path.endswith(".h") or not os.path.exists(zephyr_base + "/" + f.path): + continue + + for script in coccinelle_scripts: + script_path = os.getenv("ZEPHYR_BASE") + "/" + script + cocci = sh.coccicheck( + "--mode=report", + "--cocci=" + + script_path, + f.path, + **sh_special_args) + parse_coccinelle(cocci, violations) + + for hunk in f: + for line in hunk: + if line.is_added: + violation = "{}:{}".format(f.path, line.target_line_no) + if violation in violations: + v = {} + v['message'] = "\t\n".join(violations[violation]) + v['file'] = violation.split(":")[0] + v['line'] = violation.split(":")[1] + v['annotation_level'] = "failure" + vlist.append(v) + numViolations += 1 + if args.output: + with open(args.output, "a+") as fp: + fp.write("{}:{}\n".format( + violation, "\t\n".join( + violations[violation]))) + else: + print( + "{}:{}".format( + violation, "\t\n".join( + violations[violation]))) + with open('violations.json', 'w') as outfile: + json.dump(vlist, outfile) + return numViolations + + +if __name__ == "__main__": + ret = main() + exit(ret) diff --git a/scripts/coccinelle/identifier_length.cocci b/scripts/coccinelle/identifier_length.cocci index 29ad406d5b3d0..fee4015649da7 100644 --- a/scripts/coccinelle/identifier_length.cocci +++ b/scripts/coccinelle/identifier_length.cocci @@ -26,5 +26,5 @@ pos << r_idlen.p; @@ if (len(id) > 31): - msg="WARNING: Identifier %s length %d > 31" % (id, len(id)) + msg="WARNING: Violation to rule 5.1 or 5.2 (Identifiers shall be distinct) %s length %d > 31" % (id, len(id)) coccilib.report.print_report(pos[0], msg) diff --git a/scripts/coccinelle/reserved_names.cocci b/scripts/coccinelle/reserved_names.cocci new file mode 100644 index 0000000000000..af383db411073 --- /dev/null +++ b/scripts/coccinelle/reserved_names.cocci @@ -0,0 +1,92 @@ +// Check violations for rule 5.7 +// https://gitlab.com/MISRA/MISRA-C/MISRA-C-2012/Example-Suite/-/blob/master/R_21_02.c +// +// Confidence: Moderate +// Copyright: (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +virtual report + +@initialize:python@ +@@ + +@common_case@ +position p; +identifier t, v; +expression E; +type T; +@@ +( +struct t *v@p; +| +struct t v@p; +| +union t v@p; +| +T v@p; +| +T *v@p; +| +struct t *v@p = E; +| +struct t v@p = E; +| +union t v@p = E; +| +T v@p = E; +| +T *v@p = E; +) + +@ script:python @ +v << common_case.v; +p << common_case.p; +@@ + +msg = "WARNING: Violation to rule 21.2 (Should not used a reserved identifier) - {}".format(v) +with open("scripts/coccinelle/symbols.txt", "r") as fp: + symbols = fp.read().splitlines() + if v in symbols: + coccilib.report.print_report(p[0], msg) + +@function_match@ +type T; +identifier f; +position p; +@@ +T f@p(...) { +... +} + +@ script:python @ +v << function_match.f; +@@ + +msg = "WARNING: Violation to rule 21.2 (Should not used a reserved identifier) - {}".format(v) +with open("scripts/coccinelle/symbols.txt", "r") as fp: + symbols = fp.read().splitlines() + if v in symbols: + coccilib.report.print_report(p[0], msg) + +@function_parameter@ +type T1, T2; +identifier function, v; +position p; +parameter list[n] P1; +parameter list[n1] P2; +@@ +T1 function(P1, T2 *v@p, P2) { +... +} + +@ script:python @ +v << function_parameter.v; +p << function_parameter.p; +@@ + +msg = "WARNING: Violation to rule 21.2 (Should not used a reserved identifier) - {}".format(v) +with open("scripts/coccinelle/symbols.txt", "r") as fp: + symbols = fp.read().splitlines() + if v in symbols: + coccilib.report.print_report(p[0], msg) diff --git a/scripts/coccinelle/same_identifier.cocci b/scripts/coccinelle/same_identifier.cocci new file mode 100644 index 0000000000000..8bb3bdcd1663e --- /dev/null +++ b/scripts/coccinelle/same_identifier.cocci @@ -0,0 +1,76 @@ +// Check violations for rule 5.7 +// https://gitlab.com/MISRA/MISRA-C/MISRA-C-2012/Example-Suite/-/blob/master/R_05_07.c +// +// Confidence: Moderate +// Copyright: (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +virtual report + +@initialize:python@ +@@ + +@common_case@ +position p; +identifier t, v; +@@ +( +struct t *v@p; +| +struct t v@p; +| +union t v@p; +) + +@ script:python @ +t << common_case.t; +v << common_case.v; +p << common_case.p; +@@ + +msg = "WARNING: Violation to rule 5.7 (Tag name should be unique) tag: {}".format(v) +if t == v: + coccilib.report.print_report(p[0], msg) + +@per_type@ +type T; +identifier v; +position p; +@@ +( +T v@p; +| +T *v@p; +) + +@ script:python @ +t << per_type.T; +v << per_type.v; +p << per_type.p; +@@ + +msg = "WARNING: Violation to rule 5.7 (Tag name should be unique) tag: {}".format(v) +if t == v: + coccilib.report.print_report(p[0], msg) + +@function_match@ +type T1, T2; +identifier function, v; +position p; +parameter list[n] P1; +parameter list[n1] P2; +@@ +T1 function(P1, T2 *v@p, P2) { +... +} + +@ script:python @ +v << function_match.v; +t << function_match.T2; +p << function_match.p; +@@ + +msg = "WARNING: Violation to rule 5.7 (Tag name should be unique) tag: {}".format(v) +if v == t.split(" ")[-1]: + coccilib.report.print_report(p[0], msg) diff --git a/scripts/coccinelle/symbols.txt b/scripts/coccinelle/symbols.txt new file mode 100644 index 0000000000000..3b32b3800cd88 --- /dev/null +++ b/scripts/coccinelle/symbols.txt @@ -0,0 +1,293 @@ +abort +abs +acos +asctime +asctime_r +asin +assert +atan +atan2 +atexit +atof +atoi +atol +bsearch +btowc +calloc +catclose6 +catgets6 +catopen6 +ceil +clearerr +clock +cos +cosh +ctime +ctime64 +ctime_r +ctime64_r +difftime +difftime64 +div +erf +erfc +exit +exp +fabs +fclose +fdopen5 +feof +ferror +fflush1 +fgetc1 +fgetpos1 +fgets1 +fgetwc6 +fgetws6 +fileno5 +floor +fmod +fopen +fprintf +fputc1 +fputs1 +fputwc6 +fputws6 +fread +free +freopen +frexp +fscanf +fseek1 +fsetpos1 +ftell1 +fwide6 +fwprintf6 +fwrite +fwscanf6 +gamma +getc1 +getchar1 +getenv +gets +getwc6 +getwchar6 +gmtime +gmtime64 +gmtime_r +gmtime64_r +hypot +isalnum +isalpha +isascii4 +isblank +iscntrl +isdigit +isgraph +islower +isprint +ispunct +isspace +isupper +iswalnum4 +iswalpha4 +iswblank4 +iswcntrl4 +iswctype4 +iswdigit4 +iswgraph4 +iswlower4 +iswprint4 +iswpunct4 +iswspace4 +iswupper4 +iswxdigit4 +isxdigit4 +j0 +j1 +jn +labs +ldexp +ldiv +localeconv +localtime +localtime64 +localtime_r +localtime64_r +log +log10 +longjmp +malloc +mblen +mbrlen4 +mbrtowc4 +mbsinit4 +mbsrtowcs4 +mbstowcs +mbtowc +memchr +memcmp +memcpy +memmove +memset +mktime +mktime64 +modf +nextafter +nextafterl +nexttoward +nexttowardl +nl_langinfo4 +perror +pow +printf +putc1 +putchar1 +putenv +puts +putwc6 +putwchar6 +qsort +quantexpd32 +quantexpd64 +quantexpd128 +quantized32 +quantized64 +quantized128 +samequantumd32 +samequantumd64 +samequantumd128 +raise +rand +rand_r +realloc +regcomp +regerror +regexec +regfree +remove +rename +rewind1 +scanf +setbuf +setjmp +setlocale +setvbuf +signal +sin +sinh +snprintf +sprintf +sqrt +srand +sscanf +strcasecmp +strcat +strchr +strcmp +strcoll +strcpy +strcspn +strerror +strfmon4 +strftime +strlen +strncasecmp +strncat +strncmp +strncpy +strpbrk +strptime4 +strrchr +strspn +strstr +strtod +strtod32 +strtod64 +strtod128 +strtof +strtok +strtok_r +strtol +strtold +strtoul +strxfrm +swprintf +swscanf +system +tan +tanh +time +time64 +tmpfile +tmpnam +toascii +tolower +toupper +towctrans +towlower4 +towupper4 +ungetc1 +ungetwc6 +va_arg +va_copy +va_end +va_start +vfprintf +vfscanf +vfwprintf6 +vfwscanf +vprintf +vscanf +vsprintf +vsnprintf +vsscanf +vswprintf +vswscanf +vwprintf6 +vwscanf +wcrtomb4 +wcscat +wcschr +wcscmp +wcscoll4 +wcscpy +wcscspn +wcsftime +wcslen +wcslocaleconv +wcsncat +wcsncmp +wcsncpy +wcspbrk +wcsptime +wcsrchr +wcsrtombs4 +wcsspn +wcsstr +wcstod +wcstod32 +wcstod64 +wcstod128 +wcstof +wcstok +wcstol +wcstold +wcstombs +wcstoul +wcsxfrm4 +wctob +wctomb +wctrans +wctype4 +wcwidth +wmemchr +wmemcmp +wmemcpy +wmemmove +wmemset +wprintf6 +wscanf6 +y0 +y1 +yn