NCS Does Not Respect C Rule Against Function Overloads Under Certain Conditions

During a review of production firmware I noticed an oddity that should cause a compiler error but it somehow does not.

In C, a function may not be overloaded. There are exceptions to this (with _Generic), but we are not engaging with this functionality. We have accidentally included a function overload in a C source file, which the Intellisense correctly marks as an error. However, the compiler does not think it is an error. I am using NCS 2.5.1 with the ARM GNU toolchain 9-2019-q4-major. Zephyr version 3.4.99. I modified the blinky sample application to replicate the issue.

Consider this code:

void test();

void function()
{
    test();
}

void test(void * arg)
{
    arbitrary_code();
}

void function2()
{
    test(NULL);
}

In the code, test() is initially declared to be parameter-less and then invoked. However, further down test() is defined as a parametrized function and invoked as such. This should cause an error in C. I tried this with a different set of build tools (IAR) and they correctly identified this as an error.

Interestingly, if you change the order of the statements, the error is caught. It seems that this compiler glitch only happens if you have a declaration with its invocation written before the function is "redefined" and used with the other signature.

Parents
  • Hi,

    This likely occurs because of how lenient or strict different compilers are with the checking. In your case, even though function overloading is not allowed, you actually have two versions of the test function.

    So in your sample, you first have a function declaration as:

    void test();

    Now, C is less strict about function declarations compared to C++. Hence when you have this declaration it likely understands it as a function which can take any arguments and return a void. So later when you have the definition as follows:

    void test(void * arg)
    {
        arbitrary_code();
    }

    It does not actually violate what you have declared before. What you have done here is incomplete function prototyping. Certain compilers are lenient with this and others like the IAR are a bit more strict with this. The better solution is to avoid incomplete function prototyping and declare it properly always.

    Hope this helps.

    Regards,

    Priyanka

Reply
  • Hi,

    This likely occurs because of how lenient or strict different compilers are with the checking. In your case, even though function overloading is not allowed, you actually have two versions of the test function.

    So in your sample, you first have a function declaration as:

    void test();

    Now, C is less strict about function declarations compared to C++. Hence when you have this declaration it likely understands it as a function which can take any arguments and return a void. So later when you have the definition as follows:

    void test(void * arg)
    {
        arbitrary_code();
    }

    It does not actually violate what you have declared before. What you have done here is incomplete function prototyping. Certain compilers are lenient with this and others like the IAR are a bit more strict with this. The better solution is to avoid incomplete function prototyping and declare it properly always.

    Hope this helps.

    Regards,

    Priyanka

Children
Related