This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: extern const initialized warns in C


Also the warning did not include a link explaining the desired workaround.


Since you advocate for static...and I know it has big value..

There are the following reasons against static:

 - It is prohibited in some coding conventions.
    They instead hide symbols by omitting them from any headers.

 - It allows/encourages symbols duplicated from a human point of view,
   leading to harder to read code; but this is also the point and good,
   it offers scope to pick shorter names, or at least hide
   names (you can still strive for globally unique names, in
   case the symbols later have to be made extern)
   
 - it leads to accidental duplication, static int foo = 123 in a header

 - There are toolsets that don't resolve statics in disassembly

 - It only allows for sharing within a file and hiding from all others,
   it doesn't allow sharing for within a few files and hiding from others

 - It sort of doesn't work with "unity builds" old fashioned LTO/LTCG where one
   source file includes the rest
   

   I think a linker switch to report symbols that could be static
   might be useful.
   
   I find the "scoping" too hard to pass it, and if I need to make
   the symbol extern in future, I can afford a rename to do it.
   

    - Jay




From: Jay K
Sent: Monday, January 22, 2018 9:31 AM
To: David Brown; gcc
Subject: Re: extern const initialized warns in C
  


By this argument there is a missing warning for the equivalent:

  const int foo = 123;

with no previous extern declaration.

As well, there is no warning in C++.
All three constructs are equivalent, yet only one gets a warning.

Interesting point, that I had not realized, and with an often acceptable
workaround, however also there exist coding conventions that prohibit use of static.
Instead they "hide" things by omitting them from headers only.

That can still be worked around, just put the declaration right before the definition,
in the same source file.

I realize there are many arguments for and against file level static.

 - Jay  


From: David Brown <david@westcontrol.com>
Sent: Monday, January 22, 2018 8:32 AM
To: Jay K; gcc
Subject: Re: extern const initialized warns in C
  

On 21/01/18 08:12, Jay K wrote:
> extern const int foo = 123;
> 
> 
> 
> Why does this warn?
> This is a valid portable form, with the same meaning
> across all compilers, and, importantly, portably
> to C and C++.
> 
> I explicitly do not want to say:
> 
>   const int foo = 123
> 
> because I want the code to be valid and have the same meaning
> in C and C++ (modulo name mangling).
> 
> I end up with:
> 
> // Workaround gcc warning.
> #ifdef __cplusplus
> #define EXTERN_CONST extern const
> #else
> #define EXTERN_CONST const
> #endif
> 
> 
> EXTERN_CONST int foo = 123;
> 
> and having to explain it to people.
> 

<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977>


45977 – "warning: 'i' initialized and declared 'extern ...
gcc.gnu.org
GCC Bugzilla – Bug 45977 "warning: 'i' initialized and declared 'extern'" could use a separate warning flag controlling it Last modified: 2017-07-26 15:36:22 UTC


45977 – "warning: 'i' initialized and declared 'extern ...
gcc.gnu.org
GCC Bugzilla – Bug 45977 "warning: 'i' initialized and declared 'extern'" could use a separate warning flag controlling it Last modified: 2017-07-26 15:36:22 UTC

This suggests that gcc authors consider mixing "extern" and
initialization to be such bad style that the compiler warns by default.
 But the "bug" is that there is no flag to turn off this warning.
(Ideally every warning should have a matching flag, even if the warning
is enabled by default.)

Usually you do not want to have "extern" and initialisation in the same
line - it indicates a questionable organisation of your sources which is
more likely to be error-prone than the standard idioms.  (I say
"questionable", not necessarily wrong - but certainly I would question
it if I saw it in source code.)

Normally you want:

// file.h
// declaration, not definition
extern const int foo;

// file.c
#include <file.h>
// definition
const int foo = 123;

// otherfile.c
#include <file.h>
int usefoo(void) { return foo; }


The key advantages of this sort of setup are a cleaner separation
between declarations (which you need to /use/ things) and the
definitions (which should normally only exist once in the program -
certainly for C).  The declarations and definitions only exist in one
place, and they are checked for consistency - there are no "extern"
declarations lying around in C files that might get out of step from
changes in the headers or other files with definitions.

To be consistent with this, and to work consistently with C and C++, I
have a strict policy that a C (or C++) file never contains  declarations
without definitions (and initialisations as needed), with each
definition either also declared as "extern" in a matching header file,
or it is declared as "static".

This sort of arrangement is very common - though many people are lazy
about using "static".  (In C++, you can also use anonymous namespaces,
but "static" works for consistency between C and C++.)


Still, gcc should have a flag to disable this warning if you have reason
to use "extern const int foo = 123;" - it is, after all, correctly
defined C code.



> $ cat 1.c
> extern const int foo = 123;
> $ $HOME/gcc720/bin/gcc -c -S 1.c
> 1.c:1:18: warning: 'foo' initialized and declared 'extern'
>  extern const int foo = 123;
>                   ^~~
> $ $HOME/gcc720/bin/gcc -c -S -xc++ -Wall -pedantic 1$ $HOME/gcc720/bin/gcc -v
> Using built-in specs.
> 
> COLLECT_GCC=/Users/jay/gcc720/bin/gcc
> COLLECT_LTO_WRAPPER=/Users/jay/gcc720/libexec/gcc/x86_64-apple-darwin16.7.0/7.2.0/lto-wrapper
> Target: x86_64-apple-darwin16.7.0
> Configured with: ../gcc-7.2.0/configure -prefix=/Users/jay/gcc720 -disable-nls -disable-bootstrap
> Thread model: posix
> gcc version 7.2.0 (GCC) $ 
> 
> 
> Thank you,
>  - Jay
> 
> 
> 
>      
> 

        

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]