0

We have the following non-conforming C code with the definitions at file scope:

const int n = 5;
int m = n; // n is not a constant expression

It compiles without a warning with gcc-10.3.0 and flags -c -Wall -pedantic -std=c99. It's fine because of 6.6p10

An implementation may accept other forms of constant expressions.

Though a warning should be raised due to -pedantic option.

However, the following code (also at file scope):

const int n = 5;
int A[n];

fails with a compilation error:

error: variably modified ‘A’ at file scope

And it's strange because assuming treating n as constant expression the declaration above should be equivalent to:

int A[5];

Neither Variable Modified types (i.e. VLA) at file scope nor using non-const values in an initializer for variables with static storage is allowed by C standard.

What is the reason of treating n as a constant expression in one context while not in the other?


Edit

This question is GCC specific.

This question is not a duplicate of stackoverflow.com/q/59065111/4989451 because I am not asking why no warning is raised but why "extended" constant expression is treated differently in "size expression" and "initializer".


Edit 2

It looks that I have incorrectly assumed that GCC treats n as a constant expression. It rather accepts n as an initializer for objects with static storage. I was tricked by the lack of warning about non-constant when compiling in "pedantic" mode. It's likely a compiler bug. With such an interpretation, this question is indeed a duplicate.


Edit3

This question and answers looks very related: Why does gcc/clang handle code slightly differently? (Example given)

tstanisl
  • 13,520
  • 2
  • 25
  • 40
  • @trentcl - For static objects, they do – StoryTeller - Unslander Monica Sep 07 '21 at 16:01
  • @trentcl the OP is talking about variables at file scope. – Gerhardh Sep 07 '21 at 16:02
  • The amazing reopening to answer dupes is happening again, I see – StoryTeller - Unslander Monica Sep 07 '21 at 16:03
  • 1
    Fellow Mjolnir holders, here is what I closed it with https://stackoverflow.com/questions/59065111 - Judge for yourselves – StoryTeller - Unslander Monica Sep 07 '21 at 16:04
  • 3
    How is that a duplicate? This question is asking about reason for different handling which is not addressed in the dupe at all. – Gerhardh Sep 07 '21 at 16:04
  • 2
    @Gerhardh - Do read. "This is very likely caused by the both GCC and Clang being compiler suites for C++ as well. In C++ i is a valid initializer for j." – StoryTeller - Unslander Monica Sep 07 '21 at 16:04
  • 2
    The answer to both questions is the same: this is a non standard extension. Moreover, you should not simply assert your question is not a duplicate in comments but [edit] the question to clarify how it is different. – trent Sep 07 '21 at 16:08
  • @EricPostpischil, I've deleted the comment and moved it into EDIT section – tstanisl Sep 07 '21 at 16:20
  • 1
    @trentcl: “this is a non standard extension” is not a complete answer. Any extension is designed and implemented for some reason. If an implementor has chosen to accept a static `const int` as a constant in one place and not another, there was some reason for that, and “this is a non standard extension” does not provide that reason. – Eric Postpischil Sep 07 '21 at 16:23
  • It might be unintentional (clang accepts the first too lets you off with a warning for the array). Gcc could also rationalize the behavior by saying it accepts `int m = n;` as an extension that has nothing to do with treating this `n` as "another form of constant expression". It might be a good idea to try and not to depend on such quirks. – Petr Skocik Sep 07 '21 at 16:29
  • 2
    The only way to really answer this would be in terms of compiler internals - is that what you are looking for? As it stands it isn't really a question about the C language itself. – Nate Eldredge Sep 07 '21 at 16:33
  • One hypothesis: C++ has added features for compile-time evaluations that result in new things being accepted as constants. Support for that in GCC may have “leaked” (intentionally or unintentionally) into allowing some additional things as constants in initializers. However, the leakage might not have affected GCC’s treatment of array dimensions. – Eric Postpischil Sep 07 '21 at 16:37
  • @NateEldredge, maybe but I'm rather interested why GCC developers made such a distinction. In C++ both variants wre fine so it can't be some relict from shared c/c++ implementation – tstanisl Sep 07 '21 at 16:40
  • 3
    It looks like `int m = n;` only started to be supported in GCC 8. Prior to that it gives `error: initializer element is not constant`. – Nate Eldredge Sep 07 '21 at 16:46
  • @NateEldredge great finding maybe GCC people are adding a true named and typed constants to C in a form of 'static const'. It would be a great extension, especially in mainstream C implementation – tstanisl Sep 07 '21 at 16:57
  • I agree with @StoryTeller-UnslanderMonica that the proposed duplicate is indeed a duplicate. The duplicate is asking why the inconsistency identified in this question is present in the compilers. It isn't to give a great answer — "because that's the way the compilers behave" isn't very satisfying, but it is pretty much the only answer available. You can try reporting it to the maintainers of GCC (and/or Clang), but I have a strong suspicion that you will not have much success in doing so (but I may be wrong on that). – Jonathan Leffler Sep 07 '21 at 17:30
  • @JonathanLeffler, ok. I've wrongly assumed that GCC treats 'n' as a constant expression. It just accepts it as an initializer for objects with static storage. I got tricked by a lack of any warning what is likely a bug. Indeed, with such an interpretation, this question is a duplicate and the answer is satisfactory. Thanks – tstanisl Sep 07 '21 at 17:59
  • 1
    @tstanisl: I agree that the compilers are not following the letter of the C standard, despite your efforts to get them to do so. This sort of thing is why it is good to test your code with as many different compilers as possible — different compilers have different extensions and blind spots. It can be hard work to eliminate all the accidental deviations from Standard C in your code. – Jonathan Leffler Sep 07 '21 at 18:03
  • @JonathanLeffler, this thread seems very related to my question:https://stackoverflow.com/questions/66144082/why-does-gcc-clang-handle-code-slightly-differently-example-given – tstanisl Sep 09 '21 at 20:07
  • @tstanisl — I agree; I've added it to the list of questions in the closure reason. – Jonathan Leffler Sep 09 '21 at 20:10
  • Disagree that this is a duplicate; the two linked questions address the two cases but neither of them answers OP's question which is how the two cases can be different -- it seems to me this indicates a compiler bug, whereas neither of the two cases on their own would be indicative of a bug – M.M Sep 09 '21 at 21:11

0 Answers0