public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* extern const initialized warns in C
       [not found] <MWHPR18MB121493D9F2292547E0AF6C3AE6ED0@MWHPR18MB1214.namprd18.prod.outlook.com>
@ 2018-01-21  7:12 ` Jay K
  2018-01-21 12:08   ` Georg-Johann Lay
                     ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Jay K @ 2018-01-21  7:12 UTC (permalink / raw)
  To: gcc

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.

$ 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



     

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-21  7:12 ` extern const initialized warns in C Jay K
@ 2018-01-21 12:08   ` Georg-Johann Lay
  2018-01-22  9:44     ` Franz Sirl
  2018-01-22 15:20     ` Jonathan Wakely
  2018-01-22  8:32   ` David Brown
  2018-01-22 15:19   ` Jonathan Wakely
  2 siblings, 2 replies; 18+ messages in thread
From: Georg-Johann Lay @ 2018-01-21 12:08 UTC (permalink / raw)
  To: Jay K; +Cc: gcc

Jay K schrieb:
> 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 also wondered about this.

In C99 §6.9.2 "External object definitions" there's actually
the following example in clause 4:

extern int i3 = 3; // definition, external linkage

Johann

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-21  7:12 ` extern const initialized warns in C Jay K
  2018-01-21 12:08   ` Georg-Johann Lay
@ 2018-01-22  8:32   ` David Brown
  2018-01-22  9:32     ` Jay K
  2018-01-22 15:19   ` Jonathan Wakely
  2 siblings, 1 reply; 18+ messages in thread
From: David Brown @ 2018-01-22  8:32 UTC (permalink / raw)
  To: Jay K, gcc

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>

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
> 
> 
> 
>      
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-22  8:32   ` David Brown
@ 2018-01-22  9:32     ` Jay K
  2018-01-22  9:39       ` Jay K
  2018-01-22  9:54       ` David Brown
  0 siblings, 2 replies; 18+ messages in thread
From: Jay K @ 2018-01-22  9:32 UTC (permalink / raw)
  To: David Brown, gcc


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

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
> 
> 
> 
>      
> 

    

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-22  9:32     ` Jay K
@ 2018-01-22  9:39       ` Jay K
  2018-01-22 10:14         ` David Brown
  2018-01-22  9:54       ` David Brown
  1 sibling, 1 reply; 18+ messages in thread
From: Jay K @ 2018-01-22  9:39 UTC (permalink / raw)
  To: David Brown, gcc

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
> 
> 
> 
>      
> 

        

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-21 12:08   ` Georg-Johann Lay
@ 2018-01-22  9:44     ` Franz Sirl
  2018-01-22 15:20     ` Jonathan Wakely
  1 sibling, 0 replies; 18+ messages in thread
From: Franz Sirl @ 2018-01-22  9:44 UTC (permalink / raw)
  To: gcc

Am 2018-01-21 um 13:08 schrieb Georg-Johann Lay:
> Jay K schrieb:
>> 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 also wondered about this.
> 
> In C99 §6.9.2 "External object definitions" there's actually
> the following example in clause 4:
> 
> extern int i3 = 3; // definition, external linkage

See https://gcc.gnu.org/ml/gcc-patches/2018-01/msg01848.html for a patch 
to make it controllable, though I wrote it for the opposite reason, 
namely to be able to turn it into an error separately (and to sync with 
the clang option).

Franz

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-22  9:32     ` Jay K
  2018-01-22  9:39       ` Jay K
@ 2018-01-22  9:54       ` David Brown
       [not found]         ` <MWHPR18MB12145B5B3E0B093993C2D214E6EC0@MWHPR18MB1214.namprd18.prod.outlook.com>
  2018-01-22 16:22         ` Vincent Lefevre
  1 sibling, 2 replies; 18+ messages in thread
From: David Brown @ 2018-01-22  9:54 UTC (permalink / raw)
  To: Jay K, gcc



On 22/01/2018 10:31, Jay K wrote:
> 
> By this argument there is a missing warning for the equivalent:
> 
>    const int foo = 123;
> 
> with no previous extern declaration.

I would like to see such a warning.  There is "-Wmissing-declarations", 
but that applies only to functions and not to objects.

(Note that in C++, "const" objects without an "extern" declaration are 
effectively "static" - in C, without the storage-class specifier const 
objects have external linkage.)

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

No, they are not the same - in C++ the linkage of a const is static 
unless you explicitly say "extern", and in C it is external unless you 
explicitly say "static".

Thus in "extern const int foo = 123;", the "extern" has a significant 
effect in C++ but in C it does nothing (other than inform the reader).

I would like to see the warning having a controlling flag.  It could 
perhaps be on by default in C and off by default in C++ to get the same 
effect as today - and then users can fine-tune to fit their style.

> 
> Interesting point, that I had not realized, and with an often acceptable
> workaround, however also there exist coding conventions that prohibit use of static.

I have never heard of such a thing in a coding standard.  C++ 
conventions might encourage the use of anonymous namespaces rather than 
C-style "static" declarations, but that would not apply to C.  I would 
consider a coding convention that discouraged static to be seriously broken.

> Instead they "hide" things by omitting them from headers only.

That is madness.  The symbols still have global linkage across the 
program, and you will get all sorts of problems when one file uses the 
same "local" identifier as another.  If you are lucky, your linker will 
tell you of the crash - but if you have enabled "common" data (i.e., you 
don't have the "-fno-common" flag) and have used the same identifier for 
two different "local" objects without explicit initialisation, you are 
going to have some serious and very hard to find bugs.

If someone asks you to write to such a coding convention, do your best 
to refuse.

> 
> 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.
> 

There are no /good/ arguments against file-level static in C, except 
perhaps temporarily while debugging (it can be easier to view non-static 
data in a debugger).  Any time file-level static can be used, it 
/should/ be used.

IMHO, of course.

mvh.,

David


>   - 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
> 
> 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
>>
>>
>>
>>        
>>
> 
>      
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-22  9:39       ` Jay K
@ 2018-01-22 10:14         ` David Brown
  2018-01-22 10:25           ` Jay K
  0 siblings, 1 reply; 18+ messages in thread
From: David Brown @ 2018-01-22 10:14 UTC (permalink / raw)
  To: Jay K, gcc

Hi,

I made some points in my other reply.  But for completeness, I'll tackle 
these too.

On 22/01/2018 10:38, Jay K wrote:
> 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.

As noted before, that is insane.  It gives no benefits but makes it easy 
to cause mistakes that are hard to find.

> 
>   - 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)

Omitting "static" also allows symbol duplication.  It just means that 
such duplication is an error in the code - which may or may not be 
caught at link time.

You /can/ have a coding convention that discourages duplicate symbol 
names - even when using "static".  That might help a little in 
understanding, but will quickly mean bloated source code that is harder 
to read and follow (because you end up with long-winded symbol names 
everywhere).

Such conventions are not scalable, are hopeless for multi-programmer 
projects, terrible for code re-use, and can make code far harder to read 
and write.

The scoping and naming in C is limited enough without omitting half the 
features it has to deal with modularisation.

>     
>   - it leads to accidental duplication, static int foo = 123 in a header

It is quite simple - don't do that.  It is appropriate for constant data 
- "static const int foo = 123;" in a header will be fine, because "foo" 
has the same value everywhere and is likely to be "optimised away". 
That is the reason C++ makes "const int foo = 123;" effectively static.

Headers (in C, and mostly in C++) are for /declarations/, not 
definitions - at least if you want to write structured and modular code.

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

Statics are local to the file.  Disassemblies should show them when they 
are used.  For the tiny, tiny proportion of C programmers that ever use 
a disassembler, if their toolchains are not good enough then they should 
get better toolchains.  It should /never/ be a problem when using 
assembly listing files generated by the compiler, which are almost 
always more useful than disassembling object code.

Making a coding convention to suit this requirement is like making 
gloves with 6 fingers so that they fit people with an extra digit.

> 
>   - 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

C has no good way to allow sharing between a few files and hiding from 
others.  Such shared identifiers must be program-wide global.  But that 
does /not/ mean you should make /everything/ program-wide global!  It 
means you should minimise such sharing, prefix such shared names in a 
way likely to minimise conflicts, and organise your source code modules 
as best you can.

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

It works /exactly/ as well.  Such "unity builds" need symbols to have 
different identifiers - but you can quite happily declare them "static".

You seem to be under the impression that using "static" forces you to 
use duplicate names for different objects in different files.  That is 
not true - it merely /allows/ it.  You can still have a convention 
requiring different identifiers in different modules.  It is a bad idea, 
IMHO, but omitting "static" makes it far worse.

> 
>     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.

I am not sure what you mean by that.

mvh.,

David


>     
> 
>      - 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
>>
>>
>>
>>        
>>
> 
>          
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-22 10:14         ` David Brown
@ 2018-01-22 10:25           ` Jay K
  0 siblings, 0 replies; 18+ messages in thread
From: Jay K @ 2018-01-22 10:25 UTC (permalink / raw)
  To: David Brown, gcc

> 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.


I mean, I actually like like the ability to shorten file level static symbols.


As you point out, true, you can have it both ways, static does not force shortening, merely allows it, and protects you from inadvertant duplication.


Really, the prohibition against file level static is used in large code bases.

You already have to chose unique extern names, and depend on the linker to diagnose duplicate externals for them.

Extending this by barring statics isn't necessarily significant.

Such code bases prefix every extern identifier with some "local" prefix, and any missing prefix is easy to spot and a stylistic mistake.

(i.e. local to the subsystem or directory -- I realize it is the very definition of "local" that makes or break this)


I understand that hiding by omission from headers is not hiding at the linker level.


I agree there are scalability problems with naming in C, but it isn't clear static helps significantly.


There is an interesting side effect though that I think is not very much appreciated.

Large C code bases are more amenable to plain text search than large C++ code bases, due to the "more uniqueness" of symbols.


This plain text search aspect is one of extremely few advantages I see to C over C++, perhaps the only one.


 - Jay


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

Hi,

I made some points in my other reply.  But for completeness, I'll tackle
these too.

On 22/01/2018 10:38, Jay K wrote:
> 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.

As noted before, that is insane.  It gives no benefits but makes it easy
to cause mistakes that are hard to find.

>
>   - 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)

Omitting "static" also allows symbol duplication.  It just means that
such duplication is an error in the code - which may or may not be
caught at link time.

You /can/ have a coding convention that discourages duplicate symbol
names - even when using "static".  That might help a little in
understanding, but will quickly mean bloated source code that is harder
to read and follow (because you end up with long-winded symbol names
everywhere).

Such conventions are not scalable, are hopeless for multi-programmer
projects, terrible for code re-use, and can make code far harder to read
and write.

The scoping and naming in C is limited enough without omitting half the
features it has to deal with modularisation.

>
>   - it leads to accidental duplication, static int foo = 123 in a header

It is quite simple - don't do that.  It is appropriate for constant data
- "static const int foo = 123;" in a header will be fine, because "foo"
has the same value everywhere and is likely to be "optimised away".
That is the reason C++ makes "const int foo = 123;" effectively static.

Headers (in C, and mostly in C++) are for /declarations/, not
definitions - at least if you want to write structured and modular code.

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

Statics are local to the file.  Disassemblies should show them when they
are used.  For the tiny, tiny proportion of C programmers that ever use
a disassembler, if their toolchains are not good enough then they should
get better toolchains.  It should /never/ be a problem when using
assembly listing files generated by the compiler, which are almost
always more useful than disassembling object code.

Making a coding convention to suit this requirement is like making
gloves with 6 fingers so that they fit people with an extra digit.

>
>   - 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

C has no good way to allow sharing between a few files and hiding from
others.  Such shared identifiers must be program-wide global.  But that
does /not/ mean you should make /everything/ program-wide global!  It
means you should minimise such sharing, prefix such shared names in a
way likely to minimise conflicts, and organise your source code modules
as best you can.

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

It works /exactly/ as well.  Such "unity builds" need symbols to have
different identifiers - but you can quite happily declare them "static".

You seem to be under the impression that using "static" forces you to
use duplicate names for different objects in different files.  That is
not true - it merely /allows/ it.  You can still have a convention
requiring different identifiers in different modules.  It is a bad idea,
IMHO, but omitting "static" makes it far worse.

>
>     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.

I am not sure what you mean by that.

mvh.,

David


>
>
>      - 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 ...<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977>
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
>
>
> 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
>>
>>
>>
>>
>>
>
>
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
       [not found]         ` <MWHPR18MB12145B5B3E0B093993C2D214E6EC0@MWHPR18MB1214.namprd18.prod.outlook.com>
@ 2018-01-22 10:42           ` David Brown
  2018-01-22 11:27             ` Jay K
  0 siblings, 1 reply; 18+ messages in thread
From: David Brown @ 2018-01-22 10:42 UTC (permalink / raw)
  To: Jay K, gcc



On 22/01/2018 11:14, Jay K wrote:
> I  meant:
> 
> 
> extern const foo = 123;
> 
> 
> does not warn in C++, but by these arguments, should.
> 

Yes, I think it should.  But I am a compiler user, not a compiler 
author, so my bias is strongly towards /my/ code rather than a wider 
audience.

> 
> 
> I understand that const int foo = 123 is static in C++.
> 
> It is this difference between C and C++ and the desire to write code 
> that means the same in C and C++ is why I write extern const int foo = 
> 123 in the first place. If I was just writing C forever and not planning 
> to compile as C++ ever then I would omit the redundant extern -- and not 
> get a warning -- the other inconsistency!

As I suggested, put the declaration in the header and the definition in 
the source file.  Then it is the same code for C and C++, works 
correctly, and gives no warnings no matter what flags you use.  And it 
is modular, structured, and lets programmers see exactly what is 
"exported" from that C file by looking in a short header rather than 
digging through a long source file.

> 
> 
> To repeat for clarity:
> 
> 
>   1 C: extern const int foo = 123; => warns, for reasons explained and 
> understood even if not agreed
> 
>   2 C: const int foo = 123; => means the same thing, but no warning; 
> inconsistent?
> 
>   3 C++: extern const int foo = 123; => also no warning, inconsistent?
> 
> 
> 
> The prohibition against file level static is actually quite widespread 
> and adhered to.
> 

Can you give references or links?  As I say, I think such a convention 
is /seriously/ wrong.

(There are plenty of other conventions that I think are wrong - even 
famous and "professional" standards like MISRA have some daft ideas.)

> 
> Along with it, of course, comes a mandate to pick globally unique names.

That mandate I can understand.  There are rational justifications for 
it, even though I don't agree with them and think it is unworkable 
except for very small and limited programs.  But there is nothing to 
stop you using "static" along with the globally unique names.

> 
> Given a large C code base with many external identifiers, the extra step 
> of barring static and requiring incrementally more symbols to be unique 
> is not clearly a big deal. I already have to ensure uniqueness of many 
> symbols, what is a few more?
> 

The majority of your file-level identifiers in a C file will normally 
/not/ be exported - they will only ever be used internally.  I have no 
statistics, but I'd guess that under 10% of most C file's file-level 
identifiers are used externally in my "average" C file.  That means only 
10% need to be globally unique.

> 
> 
> But I understand, perhaps in other systems, statics vastly outnumber 
> externs, and the condition would be a large increment not a small one.
> 

Yes, exactly.  Of course this sort of thing will vary somewhat depending 
on the type of coding you are doing.

> 
> 
> While I struggle not bite my tongue advocating switching from C to C++, 
> this factor seems much less sigificant or harmful.

I don't follow.  If you want to switch from C to C++, that's fine by me 
:-)  C++ gives you namespaces, which gives you another way to group your 
identifiers and control their scope.

> 
> I have actually seen and heard of the accidental duplication of symbols 
> due to static multiple times.

If you put your static variables in the C file, it is not "accidental" 
duplication - they are different objects.  If you put static (non-const) 
variables in your header files, you have misunderstood how to use header 
files in C programming.

> 
> I also do a "unity build" (one source file includes the rest) of my own 
> code to eek out a little extra performance (even while already using 
> LTO/LTCG) and had to work out the static duplication.
> 

Using "static" does not hinder that.  And it can be a significant 
benefit in performance.  So far, we have been looking at this from the 
viewpoint of code correctness, easy of reading and writing the code, and 
avoiding subtle errors.  But since you are interested in performance or 
code size, then you /really/ should be using "static" at every possible 
opportunity.  It makes a large difference - both for code size and 
speed, when you have "static" on your variables and functions that don't 
have to be globally visible.

> 
> 
> You mention the debugger ease of use.
> 
> I haven't seen debuggers struggle with static but I have seen file 
> dumpers struggle (not objdump per se, but similar)
> 
> I use the debugger as a better disassembler instead for this very 
> reason, debugger can just load up a file for examination without running 
> anything.
> 
> 
> 
> And then, you should realize there are very large systems that output 
> nightly builds with symbols, taking hours on fast machines, where 
> individual developers only build their little part of the tree, but 
> debug anything.
> 

I realise that.  And "static" is your friend there too.  I could not 
imagine trying to use a large build system or multiple developers where 
everything is global and shared, and you are trying to keep unique names 
everywhere.  It is a recipe for pointlessly increasing build times, and 
massively increasing developer time.

> 
> 
> In these systems, it behooves the mainline source to be debuggable, and 
> not rely on temporary edits and rebuilds.
> 
> That is, if you would remove static for temporary debuggability, then it 
> follows you should remove it for long term debuggability.

No, you would only remove "static" for temporary debugging of a local 
section of code - not for a big debugging session of such massive 
builds.  It is just one of the many types of small temporary code 
changes that can be helpful during debugging, such as adding "volatile" 
or extra "printf".

> 
> There is an amazing diversity of coding styles/idioms and C and C++ 
> compilers need to be ridiculously careful in imposing or suggesting 
> restrictions. I strive to be warning-free as well, perhaps untenable.

Yes, there are lots of conventions and styles.  And as I have said, I 
fully agree that there should be a flag for this particular issue. 
People have the right to make poor choices if they want (especially 
since these poor choices are usually made by a PHB or some ancient 
programmer who hasn't noticed that the world has changed during the last 
20+ years and still thinks K&R is the defining word on C - and the 
unfortunate low-rank programmers just have to live with them).

(Apologies if I sound too harsh in my opinions here - they come from 
being an ancient programmer who /has/ noticed how things have changed 
over the last 20+ years.  But I work in a relatively narrow field - 
small systems embedded programming - and your experience may differ in 
other fields.)

mvh.,

David


> 
> 
>   - Jay
> 
> 
> 
> ------------------------------------------------------------------------
> *From:* David Brown <david@westcontrol.com>
> *Sent:* Monday, January 22, 2018 9:53 AM
> *To:* Jay K; gcc
> *Subject:* Re: extern const initialized warns in C
> 
> 
> On 22/01/2018 10:31, Jay K wrote:
>> 
>> By this argument there is a missing warning for the equivalent:
>> 
>>    const int foo = 123;
>> 
>> with no previous extern declaration.
> 
> I would like to see such a warning.  There is "-Wmissing-declarations",
> but that applies only to functions and not to objects.
> 
> (Note that in C++, "const" objects without an "extern" declaration are
> effectively "static" - in C, without the storage-class specifier const
> objects have external linkage.)
> 
>> 
>> As well, there is no warning in C++.
>> All three constructs are equivalent, yet only one gets a warning.
> 
> No, they are not the same - in C++ the linkage of a const is static
> unless you explicitly say "extern", and in C it is external unless you
> explicitly say "static".
> 
> Thus in "extern const int foo = 123;", the "extern" has a significant
> effect in C++ but in C it does nothing (other than inform the reader).
> 
> I would like to see the warning having a controlling flag.  It could
> perhaps be on by default in C and off by default in C++ to get the same
> effect as today - and then users can fine-tune to fit their style.
> 
>> 
>> Interesting point, that I had not realized, and with an often acceptable
>> workaround, however also there exist coding conventions that prohibit use of static.
> 
> I have never heard of such a thing in a coding standard.  C++
> conventions might encourage the use of anonymous namespaces rather than
> C-style "static" declarations, but that would not apply to C.  I would
> consider a coding convention that discouraged static to be seriously broken.
> 
>> Instead they "hide" things by omitting them from headers only.
> 
> That is madness.  The symbols still have global linkage across the
> program, and you will get all sorts of problems when one file uses the
> same "local" identifier as another.  If you are lucky, your linker will
> tell you of the crash - but if you have enabled "common" data (i.e., you
> don't have the "-fno-common" flag) and have used the same identifier for
> two different "local" objects without explicit initialisation, you are
> going to have some serious and very hard to find bugs.
> 
> If someone asks you to write to such a coding convention, do your best
> to refuse.
> 
>> 
>> 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.
>> 
> 
> There are no /good/ arguments against file-level static in C, except
> perhaps temporarily while debugging (it can be easier to view non-static
> data in a debugger).  Any time file-level static can be used, it
> /should/ be used.
> 
> IMHO, of course.
> 
> mvh.,
> 
> David
> 
> 
>>   - 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 ... 
> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977>
> 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
>>>
>>>
>>>
>>>        
>>>
>> 
>>      
>> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-22 10:42           ` David Brown
@ 2018-01-22 11:27             ` Jay K
  2018-01-22 13:02               ` David Brown
  0 siblings, 1 reply; 18+ messages in thread
From: Jay K @ 2018-01-22 11:27 UTC (permalink / raw)
  To: David Brown, gcc

 > If you put static (non-const)
 > variables in your header files, you have misunderstood how to use header
 > files in C programming.


 Not me, and usually const, but people do it, both.
 Even the consts can get duplicated.
 Even the simple C++
   const int one = 1;


 I can take the address of.
 It is also unusual and maybe dumb. There are too many programmers
 writing C and C++ with too little oversight to rule these out.


 The static prohibition might be too closed to identity.


 I understand about the local edit, but it behooves
 one to make the non-edited build debugable too.


 I know you can only go so far, can't litter it with printf
 or breakpoints or volatile, nor can compile it unoptimized
 and ship it, but uniquifying function/data names seems
 maybe affordable for debuggability of official builds.


  > If you want to switch from C to C++, that's fine by me


 But the rest of my team has to agree.


  > C++ gives you namespaces, which gives you
  > nother way to group your identifiers and control their scope.


I know *all* about C++ but I think for newbies it is best
to start out focusing on member functions.
Pretend there is a type global namespace to replace C's function
global namespace. That is a huge improvement on its own.


 > It makes a large difference - both for code size and speed


 I only recently learned of how static impacts ELF visibility
 and therefore performance. Windows does not work this way,
 and I'm sure MacOS does either. Non-static on Windows does not imply
 replacable at dynamic link time, not even if the function is exported.
 Symbols are always resolved directly within the dll/sharedobject by
 the static linker if they are present with no pointer or stub in the way.
 (Ok, if you incorrectly annotate as __declspec(dllexport) and you don't
 use LTO/LTCG, then you will call through a pointer, but no stub,
 no actual inter-positionableness, and it is a rare occurence.)


 There is also always a two level namespace -- imported functions are qualified
 by the dll name they are expected to be in. For multiple dlls to export
 the same function name creates no ambiguity and implies no replacement
 of one by the other, and no semantic difference depending on load order.
 Unless someone writes very wierd code calling dlopen/dlsym like crazy.
 There is no LD_PRELOAD, slight loss, and replacing e.g. operator new
 isn't really possible process-wide, only within the scope of the static link,
 and even that is so rare, that it is probably sufficient.


 There is no going out of the way to accurately simulate the static linker
 at dynamic link time. Functions are only exported if they are annotated
 in source or listed in a separate file. Not just by being non-static.


  - Jay


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



On 22/01/2018 11:14, Jay K wrote:
> I  meant:
>
>
> extern const foo = 123;
>
>
> does not warn in C++, but by these arguments, should.
>

Yes, I think it should.  But I am a compiler user, not a compiler
author, so my bias is strongly towards /my/ code rather than a wider
audience.

>
>
> I understand that const int foo = 123 is static in C++.
>
> It is this difference between C and C++ and the desire to write code
> that means the same in C and C++ is why I write extern const int foo =
> 123 in the first place. If I was just writing C forever and not planning
> to compile as C++ ever then I would omit the redundant extern -- and not
> get a warning -- the other inconsistency!

As I suggested, put the declaration in the header and the definition in
the source file.  Then it is the same code for C and C++, works
correctly, and gives no warnings no matter what flags you use.  And it
is modular, structured, and lets programmers see exactly what is
"exported" from that C file by looking in a short header rather than
digging through a long source file.

>
>
> To repeat for clarity:
>
>
>   1 C: extern const int foo = 123; => warns, for reasons explained and
> understood even if not agreed
>
>   2 C: const int foo = 123; => means the same thing, but no warning;
> inconsistent?
>
>   3 C++: extern const int foo = 123; => also no warning, inconsistent?
>
>
>
> The prohibition against file level static is actually quite widespread
> and adhered to.
>

Can you give references or links?  As I say, I think such a convention
is /seriously/ wrong.

(There are plenty of other conventions that I think are wrong - even
famous and "professional" standards like MISRA have some daft ideas.)

>
> Along with it, of course, comes a mandate to pick globally unique names.

That mandate I can understand.  There are rational justifications for
it, even though I don't agree with them and think it is unworkable
except for very small and limited programs.  But there is nothing to
stop you using "static" along with the globally unique names.

>
> Given a large C code base with many external identifiers, the extra step
> of barring static and requiring incrementally more symbols to be unique
> is not clearly a big deal. I already have to ensure uniqueness of many
> symbols, what is a few more?
>

The majority of your file-level identifiers in a C file will normally
/not/ be exported - they will only ever be used internally.  I have no
statistics, but I'd guess that under 10% of most C file's file-level
identifiers are used externally in my "average" C file.  That means only
10% need to be globally unique.

>
>
> But I understand, perhaps in other systems, statics vastly outnumber
> externs, and the condition would be a large increment not a small one.
>

Yes, exactly.  Of course this sort of thing will vary somewhat depending
on the type of coding you are doing.

>
>
> While I struggle not bite my tongue advocating switching from C to C++,
> this factor seems much less sigificant or harmful.

I don't follow.  If you want to switch from C to C++, that's fine by me
:-)  C++ gives you namespaces, which gives you another way to group your
identifiers and control their scope.

>
> I have actually seen and heard of the accidental duplication of symbols
> due to static multiple times.

If you put your static variables in the C file, it is not "accidental"
duplication - they are different objects.  If you put static (non-const)
variables in your header files, you have misunderstood how to use header
files in C programming.

>
> I also do a "unity build" (one source file includes the rest) of my own
> code to eek out a little extra performance (even while already using
> LTO/LTCG) and had to work out the static duplication.
>

Using "static" does not hinder that.  And it can be a significant
benefit in performance.  So far, we have been looking at this from the
viewpoint of code correctness, easy of reading and writing the code, and
avoiding subtle errors.  But since you are interested in performance or
code size, then you /really/ should be using "static" at every possible
opportunity.  It makes a large difference - both for code size and
speed, when you have "static" on your variables and functions that don't
have to be globally visible.

>
>
> You mention the debugger ease of use.
>
> I haven't seen debuggers struggle with static but I have seen file
> dumpers struggle (not objdump per se, but similar)
>
> I use the debugger as a better disassembler instead for this very
> reason, debugger can just load up a file for examination without running
> anything.
>
>
>
> And then, you should realize there are very large systems that output
> nightly builds with symbols, taking hours on fast machines, where
> individual developers only build their little part of the tree, but
> debug anything.
>

I realise that.  And "static" is your friend there too.  I could not
imagine trying to use a large build system or multiple developers where
everything is global and shared, and you are trying to keep unique names
everywhere.  It is a recipe for pointlessly increasing build times, and
massively increasing developer time.

>
>
> In these systems, it behooves the mainline source to be debuggable, and
> not rely on temporary edits and rebuilds.
>
> That is, if you would remove static for temporary debuggability, then it
> follows you should remove it for long term debuggability.

No, you would only remove "static" for temporary debugging of a local
section of code - not for a big debugging session of such massive
builds.  It is just one of the many types of small temporary code
changes that can be helpful during debugging, such as adding "volatile"
or extra "printf".

>
> There is an amazing diversity of coding styles/idioms and C and C++
> compilers need to be ridiculously careful in imposing or suggesting
> restrictions. I strive to be warning-free as well, perhaps untenable.

Yes, there are lots of conventions and styles.  And as I have said, I
fully agree that there should be a flag for this particular issue.
People have the right to make poor choices if they want (especially
since these poor choices are usually made by a PHB or some ancient
programmer who hasn't noticed that the world has changed during the last
20+ years and still thinks K&R is the defining word on C - and the
unfortunate low-rank programmers just have to live with them).

(Apologies if I sound too harsh in my opinions here - they come from
being an ancient programmer who /has/ noticed how things have changed
over the last 20+ years.  But I work in a relatively narrow field -
small systems embedded programming - and your experience may differ in
other fields.)

mvh.,

David


>
>
>   - Jay
>
>
>
> ------------------------------------------------------------------------
> *From:* David Brown <david@westcontrol.com>
> *Sent:* Monday, January 22, 2018 9:53 AM
> *To:* Jay K; gcc
> *Subject:* Re: extern const initialized warns in C
>
>
> On 22/01/2018 10:31, Jay K wrote:
>>
>> By this argument there is a missing warning for the equivalent:
>>
>>    const int foo = 123;
>>
>> with no previous extern declaration.
>
> I would like to see such a warning.  There is "-Wmissing-declarations",
> but that applies only to functions and not to objects.
>
> (Note that in C++, "const" objects without an "extern" declaration are
> effectively "static" - in C, without the storage-class specifier const
> objects have external linkage.)
>
>>
>> As well, there is no warning in C++.
>> All three constructs are equivalent, yet only one gets a warning.
>
> No, they are not the same - in C++ the linkage of a const is static
> unless you explicitly say "extern", and in C it is external unless you
> explicitly say "static".
>
> Thus in "extern const int foo = 123;", the "extern" has a significant
> effect in C++ but in C it does nothing (other than inform the reader).
>
> I would like to see the warning having a controlling flag.  It could
> perhaps be on by default in C and off by default in C++ to get the same
> effect as today - and then users can fine-tune to fit their style.
>
>>
>> Interesting point, that I had not realized, and with an often acceptable
>> workaround, however also there exist coding conventions that prohibit use of static.
>
> I have never heard of such a thing in a coding standard.  C++
> conventions might encourage the use of anonymous namespaces rather than
> C-style "static" declarations, but that would not apply to C.  I would
> consider a coding convention that discouraged static to be seriously broken.
>
>> Instead they "hide" things by omitting them from headers only.
>
> That is madness.  The symbols still have global linkage across the
> program, and you will get all sorts of problems when one file uses the
> same "local" identifier as another.  If you are lucky, your linker will
> tell you of the crash - but if you have enabled "common" data (i.e., you
> don't have the "-fno-common" flag) and have used the same identifier for
> two different "local" objects without explicit initialisation, you are
> going to have some serious and very hard to find bugs.
>
> If someone asks you to write to such a coding convention, do your best
> to refuse.
>
>>
>> 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.
>>
>
> There are no /good/ arguments against file-level static in C, except
> perhaps temporarily while debugging (it can be easier to view non-static
> data in a debugger).  Any time file-level static can be used, it
> /should/ be used.
>
> IMHO, of course.
>
> mvh.,
>
> David
>
>
>>   - 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 ...<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977>
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 ...
> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977>
45977 – "warning: 'i' initialized and declared 'extern ...<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977>
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


> 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
>>>
>>>
>>>
>>>
>>>
>>
>>
>>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-22 11:27             ` Jay K
@ 2018-01-22 13:02               ` David Brown
  0 siblings, 0 replies; 18+ messages in thread
From: David Brown @ 2018-01-22 13:02 UTC (permalink / raw)
  To: Jay K, gcc

Hi,

I think we are getting quite a bit off-topic for the gcc list here.  We 
should probably take the discussion to somewhere like comp.lang.c.  So I 
shall limit things to just a couple of points to round off.

On 22/01/2018 12:27, Jay K wrote:
>   > If you put static (non-const)
>   > variables in your header files, you have misunderstood how to use header
>   > files in C programming.
> 
>   Not me, and usually const, but people do it, both.
>   Even the consts can get duplicated.
>   Even the simple C++
>     const int one = 1;
> 
> 

If they get allocated memory, then this will be duplicated across all 
units that have the same const (or static const for C).  But usually 
small constants do not get put in memory - they get used directly, and 
the opportunities for constant propagation optimisations typically 
outweigh the occasional duplication of memory.  Even taking the address 
of a const does not force it to have a memory allocation (gcc is smart 
here), and if you want you can use "-fmerge-all-constants" to save space 
on duplicate constants, at the cost of possibly causing trouble for code 
that expects separate constants to have separate addresses.

>   I can take the address of.
>   It is also unusual and maybe dumb. There are too many programmers
>   writing C and C++ with too little oversight to rule these out.
> 
> 
>   The static prohibition might be too closed to identity.
> 
>   I understand about the local edit, but it behooves
>   one to make the non-edited build debugable too.

We are taking about wildly different kinds of debugging here.

> 
>   I know you can only go so far, can't litter it with printf
>   or breakpoints or volatile, nor can compile it unoptimized
>   and ship it, but uniquifying function/data names seems
>   maybe affordable for debuggability of official builds.
> 
>    > If you want to switch from C to C++, that's fine by me
> 
>   But the rest of my team has to agree.
> 
>    > C++ gives you namespaces, which gives you
>    > nother way to group your identifiers and control their scope.
> 
> 
> I know *all* about C++ but I think for newbies it is best
> to start out focusing on member functions.
> Pretend there is a type global namespace to replace C's function
> global namespace. That is a huge improvement on its own.
> 

There is no pretence needed - there /is/ the same global namespace. 
Named and anonymous namespaces are an addition, not a replacement.

> 
>   > It makes a large difference - both for code size and speed
> 
>   I only recently learned of how static impacts ELF visibility
>   and therefore performance. 

Elf visibility is a different thing.  Symbols can have external linkage 
for C but hidden visibility in elf.  Elf symbol visibility affects the 
time taken for linking, and only affects runtime performance in terms of 
dynamic linking time (time to start the executable and to link dynamic 
libraries).  It is something you want to handle carefully if you have 
large C++ libraries where you can easily end up with vast numbers of 
symbols.

> Windows does not work this way,

Windows uses COFF format, not ELF.

>   and I'm sure MacOS does either.

MacOS is BSD underneath, and uses ELF.

>  Non-static on Windows does not imply
>   replacable at dynamic link time, not even if the function is exported.
>   Symbols are always resolved directly within the dll/sharedobject by
>   the static linker if they are present with no pointer or stub in the way.
>   (Ok, if you incorrectly annotate as __declspec(dllexport) and you don't
>   use LTO/LTCG, then you will call through a pointer, but no stub,
>   no actual inter-positionableness, and it is a rare occurence.)

None of this has anything to do with "static" and the significantly 
improved optimisations it allows.

Basically, if an object or function is static and does not "escape" (by 
passing its address out of the translation unit, or similar things), 
then the compiler knows all the uses of that object.  It can inline the 
function without making extra copies, it can remove some reads or writes 
to the variable or move them across function calls, it can omit static 
objects and functions that are not used, it can pre-compute results 
based on static consts because it knows they can never change. 
Declaring things "static" opens up a wide range of optimisations, many 
of which have knock-on effects allowing more optimisations.

If you are interested in code efficiency, and you are not using "static" 
whenever possible, you are hobbling your compiler.

mvh.,

David


> 
>   There is also always a two level namespace -- imported functions are 
> qualified
>   by the dll name they are expected to be in. For multiple dlls to export
>   the same function name creates no ambiguity and implies no replacement
>   of one by the other, and no semantic difference depending on load order.
>   Unless someone writes very wierd code calling dlopen/dlsym like crazy.
>   There is no LD_PRELOAD, slight loss, and replacing e.g. operator new
>   isn't really possible process-wide, only within the scope of the 
> static link,
>   and even that is so rare, that it is probably sufficient.
> 
> 
>   There is no going out of the way to accurately simulate the static linker
>   at dynamic link time. Functions are only exported if they are annotated
>   in source or listed in a separate file. Not just by being non-static.
> 
> 
>    - Jay
> 
> 
> 
> ------------------------------------------------------------------------
> *From:* David Brown <david@westcontrol.com>
> *Sent:* Monday, January 22, 2018 10:42 AM
> *To:* Jay K; gcc
> *Subject:* Re: extern const initialized warns in C
> 
> 
> On 22/01/2018 11:14, Jay K wrote:
>> I  meant:
>> 
>> 
>> extern const foo = 123;
>> 
>> 
>> does not warn in C++, but by these arguments, should.
>> 
> 
> Yes, I think it should.  But I am a compiler user, not a compiler
> author, so my bias is strongly towards /my/ code rather than a wider
> audience.
> 
>> 
>> 
>> I understand that const int foo = 123 is static in C++.
>> 
>> It is this difference between C and C++ and the desire to write code 
>> that means the same in C and C++ is why I write extern const int foo = 
>> 123 in the first place. If I was just writing C forever and not planning 
>> to compile as C++ ever then I would omit the redundant extern -- and not 
>> get a warning -- the other inconsistency!
> 
> As I suggested, put the declaration in the header and the definition in
> the source file.  Then it is the same code for C and C++, works
> correctly, and gives no warnings no matter what flags you use.  And it
> is modular, structured, and lets programmers see exactly what is
> "exported" from that C file by looking in a short header rather than
> digging through a long source file.
> 
>> 
>> 
>> To repeat for clarity:
>> 
>> 
>>   1 C: extern const int foo = 123; => warns, for reasons explained and 
>> understood even if not agreed
>> 
>>   2 C: const int foo = 123; => means the same thing, but no warning; 
>> inconsistent?
>> 
>>   3 C++: extern const int foo = 123; => also no warning, inconsistent?
>> 
>> 
>> 
>> The prohibition against file level static is actually quite widespread 
>> and adhered to.
>> 
> 
> Can you give references or links?  As I say, I think such a convention
> is /seriously/ wrong.
> 
> (There are plenty of other conventions that I think are wrong - even
> famous and "professional" standards like MISRA have some daft ideas.)
> 
>> 
>> Along with it, of course, comes a mandate to pick globally unique names.
> 
> That mandate I can understand.  There are rational justifications for
> it, even though I don't agree with them and think it is unworkable
> except for very small and limited programs.  But there is nothing to
> stop you using "static" along with the globally unique names.
> 
>> 
>> Given a large C code base with many external identifiers, the extra step 
>> of barring static and requiring incrementally more symbols to be unique 
>> is not clearly a big deal. I already have to ensure uniqueness of many 
>> symbols, what is a few more?
>> 
> 
> The majority of your file-level identifiers in a C file will normally
> /not/ be exported - they will only ever be used internally.  I have no
> statistics, but I'd guess that under 10% of most C file's file-level
> identifiers are used externally in my "average" C file.  That means only
> 10% need to be globally unique.
> 
>> 
>> 
>> But I understand, perhaps in other systems, statics vastly outnumber 
>> externs, and the condition would be a large increment not a small one.
>> 
> 
> Yes, exactly.  Of course this sort of thing will vary somewhat depending
> on the type of coding you are doing.
> 
>> 
>> 
>> While I struggle not bite my tongue advocating switching from C to C++, 
>> this factor seems much less sigificant or harmful.
> 
> I don't follow.  If you want to switch from C to C++, that's fine by me
> :-)  C++ gives you namespaces, which gives you another way to group your
> identifiers and control their scope.
> 
>> 
>> I have actually seen and heard of the accidental duplication of symbols 
>> due to static multiple times.
> 
> If you put your static variables in the C file, it is not "accidental"
> duplication - they are different objects.  If you put static (non-const)
> variables in your header files, you have misunderstood how to use header
> files in C programming.
> 
>> 
>> I also do a "unity build" (one source file includes the rest) of my own 
>> code to eek out a little extra performance (even while already using 
>> LTO/LTCG) and had to work out the static duplication.
>> 
> 
> Using "static" does not hinder that.  And it can be a significant
> benefit in performance.  So far, we have been looking at this from the
> viewpoint of code correctness, easy of reading and writing the code, and
> avoiding subtle errors.  But since you are interested in performance or
> code size, then you /really/ should be using "static" at every possible
> opportunity.  It makes a large difference - both for code size and
> speed, when you have "static" on your variables and functions that don't
> have to be globally visible.
> 
>> 
>> 
>> You mention the debugger ease of use.
>> 
>> I haven't seen debuggers struggle with static but I have seen file 
>> dumpers struggle (not objdump per se, but similar)
>> 
>> I use the debugger as a better disassembler instead for this very 
>> reason, debugger can just load up a file for examination without running 
>> anything.
>> 
>> 
>> 
>> And then, you should realize there are very large systems that output 
>> nightly builds with symbols, taking hours on fast machines, where 
>> individual developers only build their little part of the tree, but 
>> debug anything.
>> 
> 
> I realise that.  And "static" is your friend there too.  I could not
> imagine trying to use a large build system or multiple developers where
> everything is global and shared, and you are trying to keep unique names
> everywhere.  It is a recipe for pointlessly increasing build times, and
> massively increasing developer time.
> 
>> 
>> 
>> In these systems, it behooves the mainline source to be debuggable, and 
>> not rely on temporary edits and rebuilds.
>> 
>> That is, if you would remove static for temporary debuggability, then it 
>> follows you should remove it for long term debuggability.
> 
> No, you would only remove "static" for temporary debugging of a local
> section of code - not for a big debugging session of such massive
> builds.  It is just one of the many types of small temporary code
> changes that can be helpful during debugging, such as adding "volatile"
> or extra "printf".
> 
>> 
>> There is an amazing diversity of coding styles/idioms and C and C++ 
>> compilers need to be ridiculously careful in imposing or suggesting 
>> restrictions. I strive to be warning-free as well, perhaps untenable.
> 
> Yes, there are lots of conventions and styles.  And as I have said, I
> fully agree that there should be a flag for this particular issue.
> People have the right to make poor choices if they want (especially
> since these poor choices are usually made by a PHB or some ancient
> programmer who hasn't noticed that the world has changed during the last
> 20+ years and still thinks K&R is the defining word on C - and the
> unfortunate low-rank programmers just have to live with them).
> 
> (Apologies if I sound too harsh in my opinions here - they come from
> being an ancient programmer who /has/ noticed how things have changed
> over the last 20+ years.  But I work in a relatively narrow field -
> small systems embedded programming - and your experience may differ in
> other fields.)
> 
> mvh.,
> 
> David
> 
> 
>> 
>> 
>>   - Jay
>> 
>> 
>> 
>> ------------------------------------------------------------------------
>> *From:* David Brown <david@westcontrol.com>
>> *Sent:* Monday, January 22, 2018 9:53 AM
>> *To:* Jay K; gcc
>> *Subject:* Re: extern const initialized warns in C
>> 
>> 
>> On 22/01/2018 10:31, Jay K wrote:
>>> 
>>> By this argument there is a missing warning for the equivalent:
>>> 
>>>    const int foo = 123;
>>> 
>>> with no previous extern declaration.
>> 
>> I would like to see such a warning.  There is "-Wmissing-declarations",
>> but that applies only to functions and not to objects.
>> 
>> (Note that in C++, "const" objects without an "extern" declaration are
>> effectively "static" - in C, without the storage-class specifier const
>> objects have external linkage.)
>> 
>>> 
>>> As well, there is no warning in C++.
>>> All three constructs are equivalent, yet only one gets a warning.
>> 
>> No, they are not the same - in C++ the linkage of a const is static
>> unless you explicitly say "extern", and in C it is external unless you
>> explicitly say "static".
>> 
>> Thus in "extern const int foo = 123;", the "extern" has a significant
>> effect in C++ but in C it does nothing (other than inform the reader).
>> 
>> I would like to see the warning having a controlling flag.  It could
>> perhaps be on by default in C and off by default in C++ to get the same
>> effect as today - and then users can fine-tune to fit their style.
>> 
>>> 
>>> Interesting point, that I had not realized, and with an often acceptable
>>> workaround, however also there exist coding conventions that prohibit use of static.
>> 
>> I have never heard of such a thing in a coding standard.  C++
>> conventions might encourage the use of anonymous namespaces rather than
>> C-style "static" declarations, but that would not apply to C.  I would
>> consider a coding convention that discouraged static to be seriously broken.
>> 
>>> Instead they "hide" things by omitting them from headers only.
>> 
>> That is madness.  The symbols still have global linkage across the
>> program, and you will get all sorts of problems when one file uses the
>> same "local" identifier as another.  If you are lucky, your linker will
>> tell you of the crash - but if you have enabled "common" data (i.e., you
>> don't have the "-fno-common" flag) and have used the same identifier for
>> two different "local" objects without explicit initialisation, you are
>> going to have some serious and very hard to find bugs.
>> 
>> If someone asks you to write to such a coding convention, do your best
>> to refuse.
>> 
>>> 
>>> 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.
>>> 
>> 
>> There are no /good/ arguments against file-level static in C, except
>> perhaps temporarily while debugging (it can be easier to view non-static
>> data in a debugger).  Any time file-level static can be used, it
>> /should/ be used.
>> 
>> IMHO, of course.
>> 
>> mvh.,
>> 
>> David
>> 
>> 
>>>   - 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 ... 
> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977>
> 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 ... 
>> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977>
> 45977 – "warning: 'i' initialized and declared 'extern ... 
> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977>
> 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
> 
> 
>> 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
>>>>
>>>>
>>>>
>>>>        
>>>>
>>> 
>>>      
>>> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-21  7:12 ` extern const initialized warns in C Jay K
  2018-01-21 12:08   ` Georg-Johann Lay
  2018-01-22  8:32   ` David Brown
@ 2018-01-22 15:19   ` Jonathan Wakely
  2 siblings, 0 replies; 18+ messages in thread
From: Jonathan Wakely @ 2018-01-22 15:19 UTC (permalink / raw)
  To: Jay K; +Cc: gcc

On 21 January 2018 at 07: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.

Why not simply:

extern const int foo;
const int foo = 123;

without the ugly macro?

Or, according to taste:

// Without an extern declaration, file-scope const variables are static:
extern const int foo;
const int foo = 123;

Or:

#ifdef __cplusplus
// Without an extern declaration, file-scope const variables are static:
extern const int foo;
#endif
const int foo = 123;

But your macro version is just ugly. And instead of complaining that
you have to explain it to people, why not explain it with a comment in
the code? That's what comments are for.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-21 12:08   ` Georg-Johann Lay
  2018-01-22  9:44     ` Franz Sirl
@ 2018-01-22 15:20     ` Jonathan Wakely
  2018-01-25 12:27       ` Georg-Johann Lay
  1 sibling, 1 reply; 18+ messages in thread
From: Jonathan Wakely @ 2018-01-22 15:20 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: Jay K, gcc

On 21 January 2018 at 12:08, Georg-Johann Lay wrote:
> Jay K schrieb:
>>
>> 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 also wondered about this.
>
> In C99 §6.9.2 "External object definitions" there's actually
> the following example in clause 4:
>
> extern int i3 = 3; // definition, external linkage

That's a different case. There's no advantage to the 'extern' here,
because the code means the same thing in C and C++ without the
'extern', so just leave it out.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-22  9:54       ` David Brown
       [not found]         ` <MWHPR18MB12145B5B3E0B093993C2D214E6EC0@MWHPR18MB1214.namprd18.prod.outlook.com>
@ 2018-01-22 16:22         ` Vincent Lefevre
  1 sibling, 0 replies; 18+ messages in thread
From: Vincent Lefevre @ 2018-01-22 16:22 UTC (permalink / raw)
  To: David Brown; +Cc: Jay K, gcc

On 2018-01-22 10:53:55 +0100, David Brown wrote:
> On 22/01/2018 10:31, Jay K wrote:
> > 
> > By this argument there is a missing warning for the equivalent:
> > 
> >    const int foo = 123;
> > 
> > with no previous extern declaration.
> 
> I would like to see such a warning.  There is "-Wmissing-declarations",
> but that applies only to functions and not to objects.

I would like such a warning too. FYI, a few days I fixed in bug in
MPFR, which was defining an exported symbol outside of its prefix
under some conditions and could yield problems with multiple defined
symbols once linked with GMP. This remained undetected since this
was internal to some file and was related to code obtained from GMP
(with the preprocessor involved too). Such a warning would have
detected a potential issue via automated tests since the symbol
isn't pre-declared in .h files.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-22 15:20     ` Jonathan Wakely
@ 2018-01-25 12:27       ` Georg-Johann Lay
  2018-01-25 12:29         ` Jonathan Wakely
  0 siblings, 1 reply; 18+ messages in thread
From: Georg-Johann Lay @ 2018-01-25 12:27 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Jay K, gcc

On 22.01.2018 16:20, Jonathan Wakely wrote:
> On 21 January 2018 at 12:08, Georg-Johann Lay wrote:
>> Jay K schrieb:
>>>
>>> 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 also wondered about this.
>>
>> In C99 §6.9.2 "External object definitions" there's actually
>> the following example in clause 4:
>>
>> extern int i3 = 3; // definition, external linkage
> 
> That's a different case. There's no advantage to the 'extern' here,
> because the code means the same thing in C and C++ without the
> 'extern', so just leave it out.

I'd rather like to know why GCC is throwing a warning here.

It's clear how to hack the C source, but that's a different point.

It's just the case that I don't see any problem with that construct,
and it was worth an explicit example in the standard.  Or is it
common practice to warn constructs that are "no advantage"?

Johann


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-25 12:27       ` Georg-Johann Lay
@ 2018-01-25 12:29         ` Jonathan Wakely
  2018-01-25 12:30           ` Jonathan Wakely
  0 siblings, 1 reply; 18+ messages in thread
From: Jonathan Wakely @ 2018-01-25 12:29 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: Jay K, gcc

On 25 January 2018 at 12:27, Georg-Johann Lay wrote:
> On 22.01.2018 16:20, Jonathan Wakely wrote:
>>
>> On 21 January 2018 at 12:08, Georg-Johann Lay wrote:
>>>
>>> Jay K schrieb:
>>>>
>>>>
>>>> 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 also wondered about this.
>>>
>>> In C99 §6.9.2 "External object definitions" there's actually
>>> the following example in clause 4:
>>>
>>> extern int i3 = 3; // definition, external linkage
>>
>>
>> That's a different case. There's no advantage to the 'extern' here,
>> because the code means the same thing in C and C++ without the
>> 'extern', so just leave it out.
>
>
> I'd rather like to know why GCC is throwing a warning here.
>
> It's clear how to hack the C source, but that's a different point.
>
> It's just the case that I don't see any problem with that construct,
> and it was worth an explicit example in the standard.  Or is it
> common practice to warn constructs that are "no advantage"?

Read https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977 (as already
stated earlier in the thread).

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: extern const initialized warns in C
  2018-01-25 12:29         ` Jonathan Wakely
@ 2018-01-25 12:30           ` Jonathan Wakely
  0 siblings, 0 replies; 18+ messages in thread
From: Jonathan Wakely @ 2018-01-25 12:30 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: Jay K, gcc

On 25 January 2018 at 12:29, Jonathan Wakely wrote:
> On 25 January 2018 at 12:27, Georg-Johann Lay wrote:
>> On 22.01.2018 16:20, Jonathan Wakely wrote:
>>>
>>> On 21 January 2018 at 12:08, Georg-Johann Lay wrote:
>>>>
>>>> Jay K schrieb:
>>>>>
>>>>>
>>>>> 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 also wondered about this.
>>>>
>>>> In C99 §6.9.2 "External object definitions" there's actually
>>>> the following example in clause 4:
>>>>
>>>> extern int i3 = 3; // definition, external linkage
>>>
>>>
>>> That's a different case. There's no advantage to the 'extern' here,
>>> because the code means the same thing in C and C++ without the
>>> 'extern', so just leave it out.
>>
>>
>> I'd rather like to know why GCC is throwing a warning here.
>>
>> It's clear how to hack the C source, but that's a different point.
>>
>> It's just the case that I don't see any problem with that construct,
>> and it was worth an explicit example in the standard.  Or is it
>> common practice to warn constructs that are "no advantage"?
>
> Read https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977 (as already
> stated earlier in the thread).

Also, examples in the standard exist to show what is technically
valid, not what is good coding style.

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2018-01-25 12:30 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <MWHPR18MB121493D9F2292547E0AF6C3AE6ED0@MWHPR18MB1214.namprd18.prod.outlook.com>
2018-01-21  7:12 ` extern const initialized warns in C Jay K
2018-01-21 12:08   ` Georg-Johann Lay
2018-01-22  9:44     ` Franz Sirl
2018-01-22 15:20     ` Jonathan Wakely
2018-01-25 12:27       ` Georg-Johann Lay
2018-01-25 12:29         ` Jonathan Wakely
2018-01-25 12:30           ` Jonathan Wakely
2018-01-22  8:32   ` David Brown
2018-01-22  9:32     ` Jay K
2018-01-22  9:39       ` Jay K
2018-01-22 10:14         ` David Brown
2018-01-22 10:25           ` Jay K
2018-01-22  9:54       ` David Brown
     [not found]         ` <MWHPR18MB12145B5B3E0B093993C2D214E6EC0@MWHPR18MB1214.namprd18.prod.outlook.com>
2018-01-22 10:42           ` David Brown
2018-01-22 11:27             ` Jay K
2018-01-22 13:02               ` David Brown
2018-01-22 16:22         ` Vincent Lefevre
2018-01-22 15:19   ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).