1,932
Views
0
CrossRef citations to date
0
Altmetric
Research Article

A GCC-based checker for compliance with MISRA-C's single-translation-unit rules

, , &
Article: 2222934 | Received 02 Jan 2023, Accepted 03 Jun 2023, Published online: 16 Jun 2023

Abstract

MISRA-C is a writing specification for the C programming language defined by the Motor Industry Software Reliability Association (MISRA). It establishes a set of rules to enhance the development of software that is safe, reliable, and portable. MISRA-C is widely adopted by industries such as aerospace, defense and security, telecommunications, and medical device manufacturers. We developed a static detector of code's compliance with MISRA-C's single-translation-unit rules. The code checker is based on the GNU Compiler Collection (GCC). This paper describes the strategies underlying the detector's design and implementation. For the tested benchmarks, the proposed checker is demonstrated to correctly assess compliance with or violation of all single-translation-unit rules. It can also obtain more accurate and more complete results than Cppcheck, a popular open-source checker. The source code can be downloaded from https://github.com/CCU-HPCLAB/GCC-MISRAC-Checker.

1. Introduction

Reliability and safety are significant issues during software development. As the developing code becomes larger and more complex, these issues become increasingly important. For example, the software in a modern car may have up to 100 million lines of code (Mihailovici, Citation2021). As vehicles gain increasingly complex functions, the required code will continue to grow. In the next decade, a car could run an average of about 300 million lines of code (CitationSynopsysCitationn.d.b). Ensuring that such massive amounts of code meet the developers' expectations for their execution and future maintenance will be a significant task (Bagnara et al., Citation2018Citation2019). The C programming language (ISO, Citation1999; SC22/WG14, Citation1990) is a general-purpose language that is widely used across various applications. It is also a systems programming language designed to meet the requirements of system programs, including the UNIX operating system and a series of system utilities. A weakness of its type system is that even a program with typographical errors may still be valid code. Figure  shows an example C program. In Line 8, == is mistyped as =. The intention was for *ptr to be compared with 0, but instead 0 is stored in *ptr. The statement at Line 9 will not be executed owing to the value of *ptr. In Line 12, the pointer arithmetic goes beyond the bounds of array A, so the de-reference of the pointer has undefined behavior. The C language assumes that programmers know what they are doing: any error in the code may be passed without being noticed by the language. It is also possible that the behavior of a C program cannot be predicted. Therefore, using the C language in safety-related systems requires considerable care.

Figure 1. An example of C program.

Figure 1. An example of C program.

The Motor Industry Software Reliability Association (MISRA) is an independent not-for-profit entity that aims to provide guidelines for safety- and security-related electronic systems and software. MISRA-C (MISRA C Working Group, Citation2013) is a well-defined specification for software development using the C programming language. When it was first published in 1998, MISRA-C was intended for automotive software development. It has since been widely used to ensure the reliability of software systems in various areas beyond the automobile industry, including railways, aviation, military, and healthcare. It enables the C language to balance convenience and reliability. The guidelines in MISRA-C are classified as either rules or directives. To check compliance with a directive requires additional information (e.g. design documents or specifications), whereas compliance with rules can be assessed by analyzing the source code alone. In the context of assessing compliance with the MISRA-C rules, they can be considered as being either “single-translation-unit” or “system” rules. The MISRA-C specification distinguishes between them by stating that compliance with (or violation of) a “single-translation-unit” rule within a project can be assessed by checking each translation unit independently. In contrast, compliance with a “system” rule must be assessed by checking more than one translation unit. MISRA-C:2012 (the third edition of the specification) Amendment 1  (MISRA C Working Group, Citation2016) contains 156 rules: 49 system rules and 107 single-translation-unit rules. Each rule is further classified as being mandatory, required, or advisory. Identifying any violation of the MISRA-C rules can provide information on aspects of the source code that are harmful to a program's stability and thus require revising. Marpons et al. (Citation2009) proposed a coding rule conformance checker using Ciao Prolog (Hermenegildo et al., Citation1996). The checker comprises two parts. One formalises the coding rules using the proposed domain-specific language. The coding rules are then translated into Prolog. The other part extracts necessary program information. The authors developed a GNU Compiler Collection (GCC) (Stallman, Citation2020) middle-end pass to collect the program information (i.e. Prolog facts). Rule checking detects violations using the information from both parts. The authors used 12 High-Integrity C++ (HIC++) coding rules to evaluate the proposed approach. Volanschi (Citation2008) enhanced a GCC compiler by allowing users to customise the system by adding their own rules for violation checking. Condate, a meta language, is used to specify rule patterns. The author implemented pattern matching and checking based on GCC GIMPLE representation. There were 12 different user-defined checkers selected in the experiment, which were used to detect over 500 bugs in Linux kernel version 2.4.1. The author used Condate to express these checkers and evaluate the analysis performance. Only one checker could not be expressed by Condate. Gawade et al. (Citation2014) proposed Constantine, a user-oriented rule specification framework that can provide a set of primitive rules that can be appropriately composed to form new rules. Constantine was designed and implemented as an Eclipse plug-in to ensure us-er-friendliness. The test suite (MISRA, Citation2002) for MISRA-C 1998 was used to evaluate the correctness of Constantine's detection: 75% of cases could be detected correctly.

The main objective of the prior researches mentioned above is to support user-defined rules in a compliance checker. Our work focuses on accurately detecting all MISRA-C single-translation-unit rules. For detecting MISRA-C single-translation-unit rules, their approaches need to describe and formalise the rules first, and then execute the checking process. If the works from Marpons and Volanschi are used to detect these rules, in addition to GIMPLE-level passes, modifications of the front-end part (e.g. preprocessing and parsing stages) might be required to extract all necessary information.

Several static analysis tools can detect whether a program is compliant with the MISRA-C rules. These tools are either commercial or open source. Examples of commercial software include Parasoft (CitationParasoftCitationn.d.), PC-Lint (CitationVector InformatikCitationn.d.), Helix QAC (CitationPerforce SoftwareCitationn.d.), PVS-Studio (CitationPVS-StudioCitationn.d.), IAR C-STAT (CitationIAR SystemsCitationn.d.), Coverity (CitationSynopsysCitationn.d.a), CodeSonar (CitationGrammaTechCitationn.d.), and Polyspace (CitationMathWorksCitationn.d.). The most well-known and widely used open-source tool is Cppcheck (CitationCppcheck, Citationn.d.), which can detect software bugs, undefined behavior, dangerous coding constructs, and coding style. In Cppcheck, a program is preprocessed to an internal token list. Each token can access the related syntax tree and symbol information via proper APIs. The checker analyzes the token list according to pre-defined rules. Cppcheck also contains a value-flow analysis and simple control-flow analysis to improve the correctness of the analysis. Users can easily customise checking rules to meet their needs. All these tools are third-party software independent of the compiler.

Consider the compile–edit–debug cycle during software development (Malcolm, Citation2020). It is more natural and intuitive for users to employ a compiler detecting MISRA-C rules instead of relying on third-party static checking tools. In addition, the compiler itself and compilation options can eliminate issues surrounding implementation-defined behavior. Stallman (Citation2020) is a popular open-source (under the GPL; General Public License) compiler. It generates stable and high-quality codes and is almost the de-facto standard compiler for Linux and open-source communities. If GCC had the capability to detect compliance with the MISRA-C rules, users could quickly clarify which rules were violated and avoid writing vulnerable programs.

In this paper, we develop a MISRA-C checker based on the GCC compiler infrastructure. Compared with other popular compilers (e.g. LLVM Lattner & Adve, Citation2004), GCC supports rich back-end targets (e.g. most common processors, digital signal processors, and micro-control units). Therefore, it is particularly suitable for the development of an embedded system. Our research aims to empower users to utilise commonly available compilers to verify MISRA-C compliance and develop more robust and dependable code, particularly for software used in a wide range of embedded systems with divergent requirements and specifications. GCC is most suitable for these needs, so we chose to implement the MISRA-C checker on GCC. Our modification is based GCC 7.5.0. We mainly consider single-translation-unit rules in MISRA-C:2012 Amendment 1 and design proper checking algorithms for these rules. The algorithms are implemented at the GCC preprocessor and the abstract syntax tree (AST) representation of the GCC front end, and then integrated with the GCC compiler infrastructure. A new GCC option is also added to enable MISRA-C checking. The programs in MISRA C Working Group (Citation2013) and MISRA C Working Group (Citation2016) are used as benchmark programs for the evaluation. The experimental results show that the modified GCC compiler can correctly detect compliant and non-compliant cases for the tested benchmark programs.

1.1. Contribution

The key contributions of this paper are summarised as follows.

  • A static checker for MISRA-C single-translation-unit rules. It modifies the GCC preprocessor and front end to allow checking of MIS-RA-C' single-translation-unit rules. The source code is available on GitHub: https://github.com/CCU-HPCLAB/GCC-MISRAC-Checker.

  • GCC implementation and experience. Detailed description of the implementation and experience demonstrates tracing the GCC preprocessor and front end to find program points that require modification.

  • Experiment. The modified compiler is evaluated using the selected benchmark programs. The results show that the proposed GCC can correctly detect compliance using MISRA-C's single-translation-unit rules. We also compare the results from the proposed GCC and Cppcheck, demonstrating its ability to detect more rules and display the analyzed information more accurately than Cppcheck.

2. Approach

This section describes the approach to modify the GCC to detect MISRA-C rules. For the checked programs, our modification is designed to identify code locations violating the rules and to display the violated rules. The principle of the implementation is not to interfere with the original GCC compilation process. If the source code can be compiled successfully by the original GCC compiler, the modified compiler can also compile it, even if the code breaks some rules.

2.1. GCC

The GCC C compiler cc1 consists of three parts: a front end, a middle end, and a back end. Figure  outlines the structure of the GCC architecture. First, a C program is processed by C preprocessor cpp, an independent executable. cpp handles macro expansion and header files. The output from cpp is processed in turn via these three parts during compilation. The front end reads the input, and parses and converts it into a standard AST. The AST is then converted into a unified format GENERIC. GENERIC is a language-independent representation. The middle end lowers the GENERIC into another form called GIMPLE, a three-address representation derived from GENERIC. Then GIMPLE is transformed into a static single assignment (SSA) form called GIMPLE SSA. Finally, compilation reaches the back end, where the GIMPLE SSA is transformed into the register-transfer language (RTL) representation, like a pseudo assembly code. The RTL representation is optimised, and the proper target assembly code is generated according to the RTL and target hardware-related description. The red boxes in Figure are the parts related to our work.

Figure 2. Structure of the GCC architecture.

Figure 2. Structure of the GCC architecture.

As a mature and massive compiler system, GCC has many internal diagnostics and prompts. Most of its diagnostics, error detections, and warnings are implemented in the language front end, so we focus on the execution flow of the front end. During the conversion to GENERIC, the front end checks the code against the language's lexical, type safety, and other static constraints, and then issues relevant messages according to the language specifications. This period is an opportunity to check program constructs that are strictly valid but potentially unsafe (Sebor, Citation2019). Some MISRA-C rules are already checked by existing GCC options. For example, rule 2.6–which states: “A function should not contain unused label declarations”–can be detected by the GCC option -Wunused-label. Table  lists the checkable rules and the corresponding GCC options. The options presented in the table can be triggered by other options in addition to being used alone in GCC. The description of Warning EnabledBy() in the file gcc-7.5.0/gcc/c-family/c.opt gives detailed information.

Table 1. GCC (7.5.0) options for checking MISRA-C rules.

2.2. Strategy

During its long history of development, GCC's code has become huge and complicated. There are three methods to extend GCC's static analysis capabilities to checking MISRA-C rules. The first is to use a GCC plugin. GCC plugins are loadable modules that provide extra features to the GCC compiler. Many and varied plugin APIs are available to customise features. The development of a static analyzer in GCC requires information about GIMPLE representation and analysis of the information using GCC's built-in APIs. The second method is to extend the existing GCC static analysis pass, which runs as an interprocedural analysis pass on the GIMPLE representation. The third is similar to the existing GCC front-end analysis (e.g. the options in Table ): the rules are checked for violations during program parsing. The first method has the least connection with the GCC source code repository, so upgrading to a new GCC version should theoretically allow the existing checker to remain functional. A drawback of the first two methods is that they cannot fully analyse all the single-translation-unit rules, and the third method is still needed to detect the remaining rules that cannot be handled. They also require longer analysis times than the third method. Therefore, we adopt the third method to implement the MISRA-C checker. To unify and simplify the complexity of the entire implementation, we use a four-step strategy (outlined in Figure ) to realise the support of each rule. We first understand each rule's definition and rationale, consulting the examples in the MISRA-C specification. Second, we need to locate the relevant code fragments in the GCC. There are two important built-in functions that are commonly used during the tracing of GCC's front end.

  • debug_tree()

    In GCC's front end, a tree structure is used to store the program information. Figure  shows an example tree representation. The left part is the internal tree representation corresponding to the code on the right. The numbers preceded by the @ symbol indicate the number of the tree node. Node 5 is a variable declaration node, and its name points to node 9. Node 9 is an identifier node that stores the variable name ptr. The type of node 5 is represented by node 10. Node 10 is a pointer-type node. A tree node further links to other tree nodes recording information such as variable name, type, and array maximum index. Repeating the above can represent the information of a whole program. GCC's built-in macro TREE_CODE is used to obtain the node category. Macros (e.g. TREE_OPERAND and TREE_TYPE) can traverse the tree nodes and extract the information. Much information is obtainable from tree structures. However, it is not easy to fully understand the tree structure. The function debug_tree() can dump tree information.

  • inform()

    In addition to directly observing the information carried by a tree node, the position in the original source code corresponding to a node can be obtained immediately via inform(). This function can output the program location and a suitable message. It needs two parameters: location_t and the required message to be output. location_t is the virtual position value corresponding to the original code position. This function outputs warning messages with location information. For a token or tree node, its current context and relevant information can be obtained using this function.

Figure 3. The four-step strategy for developing our code checker.

Figure 3. The four-step strategy for developing our code checker.

Figure 4. An example GCC tree structure.

Figure 4. An example GCC tree structure.

GNU Debugger (GDB) (Stallman et al., Citation2011) is another tool to find code locations requiring modification. Its backtrace capability can push back and forth the calling sequence, and then re-follow the other conditions in the path and gradually decide suitable code locations for modification. The third step is to design the checking algorithm, which is implemented and verified in the final fourth step.

3. Design and implementation

We add a new GCC option “-Wmisra-c” to enable MISRA-C checking. The option is accompanied by a variable named Wmisra_c_trigger. Using the -Wmisra-c option sets this variable to 1 in the preprocessing stage; otherwise, it will be 0. The value of this variable will be evaluated to decide whether there is a need to check the MISRA-C rules.

Limitations of space prevent full descriptions here of the implementation of each rule. Instead, three representative rules are examined to illustrate the implementation. Appendix 1 shows the files and functions modified in creating the proposed MISRA-C checker.

3.1. Rule 7.2

Rule 7.2 states: “A ‘u’ or ‘U’ suffix shall be applied to all integer constants that are represented in an unsigned type” (MISRA C Working Group, 2013, p. 60). Figure  shows the example code. In addition to variable declaration with initialization, passing function arguments also need to be checked. Traditional C does not allow the “u” suffix. Therefore, we can write a statement such as shown in Figure (a), and then compile it using the option -Wtraditional to trigger the warning message shown in Figure (b). This is an entry point to locate the relevant code fragments in GCC.

Figure 5. Example code for Rule 7.2.

Figure 5. Example code for Rule 7.2.

Figure 6. Example code and warning message for Rule 7.2.

Figure 6. Example code and warning message for Rule 7.2.

Searching the warning message can identify the code location triggering display of the warning message. It is located at the function cpp_classify_number() in gcc-7.5.0/libcpp/expr.c. The function is responsible for categorizing numeric constants. We add a flag misra_check_rule_7_2 to indicate whether a constant has the “u” suffix. When a constant lacks the suffix, the flag misra_check_rule_7_2 is set to 1. Repeated tracking and testing through GDB identifies the function c_parser_declaration_or_fndef() as being responsible for parsing a declaration or function definition. It calls the function start_decl() to get the information related to the declarator. The return value of start_decl() informs whether a variable has an unsigned integer declaration. Finally, if the declarator is an unsigned integer and the flag misra_check_rule_7_2 is set, we can issue a MISRA-C warning message related to Rule 7.2. Consider the case of function argument passing. We use a similar approach to check rule compliance in the function convert_for_assignment(). Figure  outlines the detection concept.

Figure 7. Concept of detection of compliance with Rule 7.2.

Figure 7. Concept of detection of compliance with Rule 7.2.

3.2. Rule 10.5

MISRA-C provides a model of essential type for C-type systems to support strong type-checking and enhance code portability. The essential type of an object or expression is defined as its essential type category and size, as shown in Table . Rule 10.5 states: “The value of an expression should not be cast to an inappropriate essential type” (MISRA C Working Group, 2013, p. 89). The type casts must comply with the specifications in Table . Figure  shows the example code. However, there is an exception case. An integer constant expression with the value 0 or 1 of either signedness may be cast to a type belonging to a Boolean category.

Figure 8. Example code for Rule 10.5.

Figure 8. Example code for Rule 10.5.

Table 2. Essential type categories (MISRA C Working Group, Citation2013).

Table 3. Cast restrictions for essential types (MISRA C Working Group, Citation2013).

According to the description of the rule, a relevant statement can be divided into three parts, as shown in Figure . The first part, Lvar, is the left side of the assignment operator. The second part, castT, is the data type in a type cast operator. The third part, Rvar, is the original variable or constant value at the right side of the assignment operator. We need to locate which portion of the code deals with cast expressions, and then extract the information of these three parts.

Figure 9. The three parts of an explicit type-casting statement.

Figure 9. The three parts of an explicit type-casting statement.

GCC is a mature open-source project, so the function names and variable settings in its source code mostly represent the actual implementation. With the official manual and the annotations in the source code, we can roughly locate the functions that need to be extracted and observed. Finally, we find that the function c_parser_cast_expression() in the file gcc-7.5.0/gcc/c/c-parser.c is responsible for parsing cast expressions. Figure  outlines the concept of the modification. Inside the function c_parser_cast_expression(), two local variables type_name and expr, are used to access the three parts mentioned above. Consider the statement “m=(_Bool) 0;” in Figure . Using type_name can access the declarator of variable m and the data type _Bool in the type cast operator. The integer constant and its value can be obtained using expr. Algorithm ?? detects whether any type cast to the essential type Boolean is compliant. A similar approach can be applied to check the other essential types.

Figure 10. Concept of detection of compliance with Rule 10.5.

Figure 10. Concept of detection of compliance with Rule 10.5.

3.3. Rule 14.4

Rule 14.4 states: “The controlling expression of an if statement and the controlling expression of an iteration-statement shall have essentially Boolean type” (MISRA C Working Group, 2013, p. 121). The rule makes a clearly specified type for all controlling expressions: it must essentially be a Boolean type. In the C language, a zero value is considered to be false, and non-zero values are considered to be true. To detect Rule 14.4, we have to parse the variable type in the controlling expression and then identify whether there is an operator that can change the overall operation type. Figure  shows an example. The first if statement in the figure violates the rule, because the controlling expression is an integer type. The second if statement contains a NE_EXPR operator, so the overall evaluated result is a Boolean type, which conforms to the rule. Figure  shows the concept of detecting compliance with Rule 14.4. We create two flags, misra_14_4_bool_type and misra_14_4, to record the relevant information. The former is set if the controlling expression is Boolean type. The latter indicates whether an expression has an operator that can bring a Boolean-type result. These two flags are properly set within the functions c_parser_condition() and c_parser_binary_expression(), respectively, in the file gcc-7.5.0/gcc/c/c-parser.c. If the controlling expression is not a Boolean type (i.e. misra_14_4_bool_type is not set) and the controlling expression does not contain proper operators (i.e. misra_14_4 is not set), a warning message will be issued. The program constructs that use controlling expressions contain if-else statements, for loops, while loops, and do-while loops. Four functions, c_parser_if_statement(), c_parser_for_statement(), c_parser_while_statement(), and c_parser_do_statement(), in the file gcc-7.5.0/gcc/c/c-parser.c are respectively responsible for parsing these program constructs. We need to check the two flags at these functions to handle all controlling expressions. The functions c_parser_paren_condition() and c_parser_condition() in the file gcc-7.5.0/gcc/c/c-parser.c handle the parsing of controlling expressions for the four program constructs. According to the execution flow of GCC-front-end parsing, misra_14_4_bool_type and misra_14_4 are properly set after executing the functions c_parser_paren_condition() or c_parser_condition(). Therefore, the checking code is appropriately placed after these two functions. The implementation can detect all cases related to Rule 14.4.

Figure 11. Example code for Rule 14.4.

Figure 11. Example code for Rule 14.4.

Figure 12. Concept of detection of compliance with Rule 14.4.

Figure 12. Concept of detection of compliance with Rule 14.4.

4. Experiment

Table  lists the experimental configuration used in the evaluation. The modified GCC compiler (version 7.5.0) is evaluated on a platform with an Intel 3.41 GHz Core-i7 3770 processor and 2 GB RAM running 64-bit Rocky Linux 8.4. Examples from the MISRA-C specification (MISRA C Working Group, Citation2013Citation2016) and codes from CitationMISRA-C: Example-Suite (Citationn.d.) are selected as the tested benchmark programs. We also evaluate Cppcheck using the same benchmark programs for comparison.

Table 4. Experimental configuration.

4.1. Evaluation result

Table  lists the evaluation results. The proposed checker can successfully detect all 107 single-translation-unit rules, whereas Cppcheck can only detect 90 of them. Of these 90, 10 can be only partially checked: 5.5, 6.1, 8.2, 8.8, 10.1, 11.4, 11.8, 16.3, 18.4, and 21.6. Cppcheck cannot fully detect errors in Rules 2.6, 5.2, 5.3, 5.4, 12.5, 13.6, 15.2, 15.3, 17.3, 17.4, 20.6, 20.11, 20.12, and 21.2. It reports false positives for Rules 8.8 and 12.4, and it cannot handle the exception cases in Rule 10.5. Appendix 2 shows the rules that cannot be checked by Cppcheck.

Table 5. Evaluation results.

In some cases, a statement does not violate only one MISRA-C rule. The example in Figure  illustrates the detection situation for a statement simultaneously violating multiple rules. The macro ntohll(x) in Figure violates Rules 2.2, 10.1, 10.3, 10.4, and 10.8. Our checker accurately identifies all the violations in this case. Figure  shows the partial results. In contrast, Cppcheck shows only one violation warning related to the macro ntohll(x); Figure  shows its output screenshot. Overall, the proposed checker can obtain more accurate and more complete violation results than Cppcheck.

Figure 13. Example of a single statement violating multiple rules.

Figure 13. Example of a single statement violating multiple rules.

Figure 14. Output screenshot of the proposed MISRA-C checker.

Figure 14. Output screenshot of the proposed MISRA-C checker.

Figure 15. Output screenshot of Cppcheck.

Figure 15. Output screenshot of Cppcheck.

5. Conclusion

As computer systems become ever more closely integrated into our daily lives, the importance of ensuring their reliability and stability increases. Following the MISRA-C rules for software development can ensure that programs are safe and reliable. Doing so can also improve portability. The GCC is widely used by individuals and industries during software development. This paper implements a MISRA-C compliance checker based on the GCC infrastructure. We focus on single-translation-unit rules. The modified GCC compiler can correctly detect all single-translation-unit rules for the tested benchmark programs. Compared with Cppcheck, the proposed checker achieves more accurate and more complete results. When considering the compile–edit–debug cycle of software development, it is more natural and intuitive for users to use a compiler to detect MISRA-C rules than to rely on third-party static checking tools. The present work could help programmers develop software that is less error-prone and thereby contribute to building more reliable software systems using the readily available GCC compiler. The compiler can help improve the quality of whole software systems' development and usage and reduce the costs associated with software development and maintenance. This should improve efficiency in the development and use of computer systems.

The MISRA-C rules are either single-translation-unit or system rules. A system rule requires the entire program to be analyzed to assess compliance, so the analysis process is more complicated and often results in conservative results. For example, Rule 22.1 states: “All resources obtained dynamically by means of Standard Library functions shall be explicitly released.” (MISRA C Working Group, 2013, p. 172), which covers the detection of memory leaks. Our future work will focus on developing algorithms to assess compliance with system rules, making the support of MISRA-C more comprehensive. Providing adequate suggestions to fix code that violates MISRA-C rules and even automatically correcting rule violations will be additional research topics. Automated techniques could enable large and existing code bases to migrate quickly to comply with MISRA-C rules.

Disclosure statement

No potential conflict of interest was reported by the author(s).

Additional information

Funding

This work was supported by Ministry of Science and Technology, Taiwan[MOST 110-2221-E-194-019-MY3].

References

Appendices

Appendix 1. Modified files and functions

Table  lists the files and functions we modified for the proposed MISRA-C checker.

Table B1. List of files and functions modified for the proposed MISRA-C checker.

Appendix 2. Evaluation result for Cppcheck

Table  lists the rules that cannot be checked by Cppcheck.

Table C1. List of rules not checked by Cppcheck.