1

I have this code snippet here:

static double a;          // #1

void foo (void) 
{
    int a = 0;            // #2
     
    {                                // needs to be in its own block.
        extern double a;  // #3      // refers to the file scope object.        
    }
}

which GCC complain with:

"error: variable previously declared 'static' redeclared 'extern'"

for the line with extern double a; marked with #3.

and Clang complain with:

"warning: declaration shadows a variable in the global scope [-Wshadow]"

for the line with int a = 0; marked with #2, with reference to definition of a at file scope at the line marked with #1.

Online Example


Now if I comment out the line marked with #2 with int a = 0;:

    // int a = 0;            #2

it shows no warning and error anymore at both compilers.


It seems to have to do with that the definition of a "shadows" the a at file scope.

What I wonder is, that GCC seems to add the externness of a at line #3 to the file-scope a by the shadowing of a at line #3 by a in line #2.

  • What happens here exactly?

  • What does the error "error: variable previously declared 'static' redeclared 'extern'" mean exactly that I redeclare a at line #1 to have external linkage?

I don't understand what is going on. Shouldn't the extern declaration of a at the line marked #3 refer to a at line marked #1 instead of to redeclare the linkage of a in line #1?


Credits:

This question is inspired by experiments at the code of Jens Gustedt's answer to Rationale of static declaration followed by non-static declaration allowed but not vice versa.

  • As noted in [Jens' answer](https://stackoverflow.com/a/43615202/1275169), `extern double a;` refers to the object at file scope (`static double a;`). There's no shadowing - there's just one object. Also: Is `#2` relevant to the question? – P.P Jun 30 '20 at 17:30
  • @P.P Yes, it is. But why the error for "redeclaring" `a` at file-scope? Shouldn't the `extern` declaration there refer to the `static` a at file-scope instead of to redeclaring it? – RobertS supports Monica Cellio Jun 30 '20 at 17:31
  • @KamilCuk Thank you very much but I still do not understand why the error message is saying that I attempt to redeclare `a` at file scope instead of to refer to it. – RobertS supports Monica Cellio Jun 30 '20 at 18:04
  • It's undefined behavior. Compiler is allowed to do anything. It's not defined what should happen. – KamilCuk Jun 30 '20 at 18:18
  • What makes it undefined behavior, @KamilCuk? Before you answer, you might want to read [paragraph 6.2.2/4](https://port70.net/~nsz/c/c11/n1570.html#6.2.2p4) of the standard. – John Bollinger Jun 30 '20 at 18:21
  • @KamilCuk The code has undefined behavior, ok. But the compiler is just allowed to throw any message? The diagnostic has to have a reasoned meaning. That's what I want to find out. What the message is saying. – RobertS supports Monica Cellio Jun 30 '20 at 18:22
  • @RobertSsupportsMonicaCellio, a compiler is permitted to emit any messages it chooses under any circumstances. That much is a quality of implementation issue, unrelated to the standard. – John Bollinger Jun 30 '20 at 18:23
  • @JohnBollinger So it could say "*error: demons fly out of your nose*"? The message does not have to belong to any logic? That's curious. – RobertS supports Monica Cellio Jun 30 '20 at 18:25
  • 1
    Yes, @RobertSsupportsMonicaCellio. The standard describes certain situations in which a compiler must emit a diagnostic message (and this is not one of them), but it has nothing whatever to say about the *contents* of those or any other diagnostics. As I said, it is a *quality of implementation* issue. Most people would prefer a compiler whose diagnostic messages are appropriate and clear, but there is no requirement for that. – John Bollinger Jun 30 '20 at 18:29
  • So maybe Robert would like to reframe the question away from "what does the standard say" and towards "is the message inaccurate or misleading, or is there a different way to interpret it that would make more sense?" – Nate Eldredge Jun 30 '20 at 18:32
  • 1
    The CLang diagnostic seems clear enough. The GCC warning is a bit misleading, though. The *identifier* `a` is declared three times in three different scopes, and in fact each declaration refers to a different object. I suspect that the warning is related to the fact that if the middle `int a` declaration were removed then the two remaining declarations would both refer to the same object (and it would have internal linkage, not external). It *is* a bit tricksome that the presence or absence of that middle declaration affects which object a different declaration declares. – John Bollinger Jun 30 '20 at 18:36
  • The meaning of the warning message, I was looking for, has been explained to me by [@EricPostpischil](https://stackoverflow.com/users/298225/eric-postpischil) in the comments to [his answer](https://stackoverflow.com/a/52883218/12139179) at the duplicate question. Since I got no sufficient answer here, I link everyone who has the same concern in the future to there. The question is with that now solved and does not need to be reopened. Thank you for the participation and even duping. – RobertS supports Monica Cellio Jul 01 '20 at 16:43

0 Answers0