NO

Author Topic: Overzealous "Inconsistent linkage" warning message on warning level 1/default  (Read 2877 times)

Offline FRex

  • Member
  • *
  • Posts: 5
Hello. Compiling the below (example) program produces an overazealous warning message (2166).

Code: (C) [Select]
static int foo(void);

int foo(void)
{
    return 10;
}

int main(int argc, char ** argv)
{
    return 0;
}

Code: [Select]
main.c
main.c(4): warning #2166: Inconsistent linkage for 'foo', previously declared at main.c(1).
main.c(3): warning #2135: Static 'foo' is not referenced.

This is apparently explicitly allowed and must do the right/expected thing. See: https://stackoverflow.com/questions/5261299/static-keyword-in-function-declaration-can-be-missing-in-function-definition

Pelles C also does the right thing and makes the function static (which is confirmed by the 2135 warning below) but shows this confusing warning.

This is a rare situation and other compilers don't warn about it at all so it really threw me off. I think Pelles C is overzealous to warn about it at warning level 1/default with no extra flags.

Maybe the warning message could be clearer to let me (or rather other programmers who run into this, since now I know) know the right thing was done (telling me function is static after all). I had to look into it (it's kinda hard to google for this problem) since I was worried it might now work correctly but it does.

Also: the line number for 2166 is tied to the line of the opening bracket, and 2135 to the line of the function name itself, despite them both referencing the same function. It's not an issue in many/most popular bracing styles but some styles (Allman BSD style) do place opening brace in its own line and there is this mismatch then.

Here's what other compilers do:
gcc (8.2.1 with -Wall and -Wextra) = no warning about this.
clang (7.0.1 with -Wall and -Wextra) = no warning about this.
MSVC/cl ran via VS 2017 = no warning about this.
« Last Edit: March 05, 2019, 10:38:47 PM by FRex »

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2266
    • http://www.smorgasbordet.com
I can't find much useful information in that thread, mostly opinions and some quotes that seem to come from some (unspecified) C++ standard.


My C11 standard and C17 draft contains the same text about linkage, and here are some quotes:

6.2.2 p3 "If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage."

6.2.2 p5 "If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern."

6.2.2 p7 "If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined."

The warning seems correct to me.
/Pelle

Offline FRex

  • Member
  • *
  • Posts: 5
This is from a draft of C11, 6.2.2:

4 For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

5 If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

The 6.2.2.4 sounds like it's exactly for this situation (together with 6.2.2.5 if there is no extern in front of the second declaration/the definition).

I ran into this in a real program/library (Lua 5.1 again, as my unsigned warning was) and none of MSVC, Clang and GCC emit such warnings. MSVC is whatever with its compliance, but the latter two are strict C compilers.

Pelles C also does the right thing right now with it, except for the warning.

Due to these 4 facts above I really think you should take a second look at entire 6.2.2 (.4 especially) to make sure it's right. If after that you think so I'm not going to argue it.