4.1. Migrating Source Code with Clang-Tidy

To aid the migration process from the cl2000 compiler to the c29clang compiler, you can use the c29clang-tidy utility either from the command line or within Code Composer Studio (CCS) Theia. This tool performs various checks of your source code and identifies code that uses cl2000-specific syntax that should be modified.

The general procedure for using the c29clang-tidy utility is as follows:

  1. Make initial code changes to reduce the number of compiler errors and false positives that will occur when running c29clang-tidy. These code changes should include:

    • Remove any definitions of the fixed width types int8_t and uint8_t.

    • Remove any extern declarations of C28 builtin functions.

    • Change any use of C28-only macros such as __TMS320C28XX__ to C29-macros such as __C29__.

  2. Run the c29clang-tidy utility using either the command line (see Running the c29clang-tidy Utility from the Command Line) or CCS Theia (see Running the c29clang-tidy Utility from CCS Theia).

  3. Make changes to your code based on the diagnostics provided.

  4. Run the c29clang-tidy utility iteratively as needed.

4.1.1. Running the c29clang-tidy Utility from the Command Line

The c29clang-tidy command line is similar to the c29clang command line.

For example, suppose your c29clang command line is as follows:

c29clang file.c -I./include -mcpu=c29.c0

The corresponding c29clang-tidy command line would be as follows:

c29clang-tidy --checks=-*,c29migration* -header-filter=.* file.c -- -I./include -mcpu=c29.c0
  • Everything on the command line after -- is treated as a normal compiler argument. Those options can be moved and duplicated as-is.

  • The --checks determines which checks are disabled and/or enabled. In this example, the initial -* turns off all checks. This is followed by c29migration*, which enables all checks that begin with “c29migration”, which includes the C28-C29 migration checks.

  • The -header-filter option tells clang-tidy which header files to check. By default, it checks none of them. In this example, .* says to check all header files using regex.

You can use the -list-checks option to list all the enabled checks. For example:

c29clang-tidy -list-checks                   \\ list default checks
c29clang-tidy -list-checks --checks=-*,c29*  \\ list all C29 checks
c29clang-tidy -list-checks --checks=*        \\ list all available checks

See the Clang-Tidy documentation for additional command line options that may be supported by c29clang-tidy. The -fix flag is not supported. You may use a .clang-tidy file as described in that documentation to configure the actions performed by c29clang-tidy.

4.1.2. Running the c29clang-tidy Utility from CCS Theia

To run the c29clang-tidy utility within CCS Theia, follow these steps:

  1. Make initial code changes to reduce the number of compiler errors and false positives that will occur when running c29clang-tidy. These code changes should include:

    • Remove any definitions of the fixed width types int8_t and uint8_t.

    • Remove any extern declarations of C28 builtin functions.

    • Change any use of C28-only macros such as __TMS320C28XX__ to C29-macros such as __C29__.

  2. The c29clang-tidy utility runs in the background for actions such as project creation, project import, and file modification. By default, the c29migration-c28-builtins, c29migration-c28-pragmas, and c29migration-c28-stdlib checks are run.

  3. A list of diagnostics found by the c29clang-tidy utility is shown in the Problems view. For example:

    ../../_images/tidy-problems.png
  4. Diagnostic messages are added to your source files. For example:

    ../../_images/tidy-code.png
  5. Make changes to your code based on the diagnostics provided.

4.1.3. Limitations

  • The c29clang-tidy utility does not analyze assembly code (.asm or inline asm() directives)

  • As with all static analyzers, false positives are possible and expected. You will need to inspect the code that results in a diagnostic message to determine whether it is a real issue.

4.1.4. Checks Performed

By default, the following checks are performed:

  • c29migration-c28-builtins

  • c29migration-c28-pragmas

  • c29migration-c28-stdlib

The other checks provided have a higher chance of returning false positives, so you will need to examine the code flagged in the diagnostics more carefully.

The c29clang-tidy utility provides the following checks:

4.1.4.1. c29migration-c28-builtins

This check looks for use of C28 intrinsics such as __fmax and __byte. It suggests alternatives if they are available. For example:

void test___add(int * m, int b) {
    __add(m, b);
}

The diagnostic warning states that the call to __add is a C28 intrinsic, which is not supported by this compiler. It suggests that you refer to the C29 intrinsic documentation to find an equivalent. In this case, it suggests using __builtin_c29_i32_add32_rm_d(b, m).

In order to use this check, you must pre-include the c28_builtins.h file on the command line.

Builtin functions are declared internally. Since they are only declared for C28, these builtin functions are treated as undefined identifiers by the C29 compiler. This is not an issue using the C89 standard, but causes errors with C99 and later and with all C++ standards. To resolve this issue, the compiler tools supply a header file that declares all C28 builtins. This file, c28-builtins.h, can be pre-included by clang-tidy. Using the command line above, add the --include option as follows:

c29clang-tidy --checks=-*,c29migration* -header-filter=.* file.c -- -I./include -mcpu=c29.c0 --include c28-builtins.h

This check is performed by default by CCS Theia. It has a low chance of returning false positives.

4.1.4.2. c29migration-c28-char-range

This check detects operations on char typed expressions that would be out of range for an 8-bit type. Because the unsigned char type is 16 bits on C28 and 8 bits on C29, overflows may occur. For example:

int ret_pos_cast(char x) {
    return (char)(x + 10000);
}

The diagnostic warning states that the cast to ‘char’ receives an out-of-range value from code that may assume a 16-bit byte type. It notes that the result of the expression is calculated as 10000.

To correct this issue, choose either C28 behavior by using a fixed-width 16-bit type (uint16_t) or accept C29 behavior and use a fixed-width 8-bit type (uint8_t).

This check is not performed by default by CCS Theia. It has a medium-to-high chance of returning false positives.

4.1.4.3. c29migration-c28-int-decls

This check suggests replacing the int and unsigned int types with int16_t and uint16_t types. For example:

void foo(int x) {  int y;}

The diagnostic warning states that you should consider using a fixed-width 16-bit type to avoid issues with the increased width of int on C29 devices.

A fix-it is available that replaces int/unsigned int types with int16_t/uint16_t types and includes <stdint.h> if it is not already included.

This check is not performed by default by CCS Theia. It has a medium-to-high chance of returning false positives.

4.1.4.4. c29migration-c28-pragmas

This check looks for use of C28 pragmas such as #pragma DATA_SECTION. It suggests alternatives if they are available. For example:

#pragma WEAK(weakx)
int weakx;

The diagnostic warning states that the WEAK pragma is a legacy TI pragma that is not supported by this compiler. It suggests that you use __attribute__((weak)) instead.

This check is performed by default by CCS Theia. It has a low chance of returning false positives.

4.1.4.5. c29migration-c28-stdlib

This check looks for calls to library functions that take a number of bytes argument where the argument is not scaled by a sizeof expression. For example:

void malloc_c_pos() {
    malloc((1+23));
}

The diagnostic warning states that the call to malloc has a byte-size argument without a sizeof expression. It suggests that you scale the size of the argument by a factor of ‘sizeof’ to avoid issues with changing byte sizes between C28 and C29.

Calls to the following library functions are checked:

  • aligned_alloc

  • calloc

  • malloc

  • realloc

  • memccpy

  • memchr

  • memcmp

  • memcpy

  • memmove

  • memset

  • strncmp

  • strncpy

  • fread

  • fwrite

This check is performed by default by CCS Theia. It has a low chance of returning false positives.

4.1.4.6. c29migration-c28-suspicious-dereference

This check detects dereferences (*) of pointers, where the source expression is integer-typed and contains an additive operation. For example:

int main() {
    *(int*)(x + 10) = 12;}

The diagnostic warning states that the pointer cast has a suspicious integer expression incremented by bytes, which are 16 bits on C28 and 8 bits on C29. It suggests that you inspect the intent of the address and scale it accordingly if needed.

This check is not performed by default by CCS Theia. It has a medium-to-high chance of returning false positives.

4.1.4.7. c29migration-c28-types

This check detects pointer arithmetic on char/int-based pointers, whose bit stride changes between C28 to C29. For example:

extern void foo(char *);void test_plus(char* x) {
    foo(x + 2);}

The diagnostic warning states that pointer arithmetic is performed on an expression with type ‘char’. Since ‘char’ is 16 bits on C28 and 8 bits on C29, you should choose either C28 behavior by using a fixed-width 16-bit type (uint16_t), or accept C29 behavior and use a fixed-width 8-bit type (uint8_t).

This check is not performed by default by CCS Theia. It has a high chance of returning false positives. This is an overly cautious check, and all matches should be individually vetted for intent and behavior.