22

As we already know, VLA (standardized in C99) are not part of the standard in C++, so the code below is "illegal" in C++:

void foo(int n) {
  int vla[n];
  for (int i = 0; i < n; ++i) {
    vla[i] = i;
  }
}

Despite of that the compiler (g++ and clang++) accepts the code as valid syntax, producing just a warning in case -pedantic flag is enabled.

ISO C++ forbids variable length array ‘vla’ [-Wvla]

My questions are:

  • Why does the compiler accept that declaration?
    Can't the compiler just reject an array in which length [is-no-know-at-compile-time]?
    Is there a sort of compatibility syntax rule to follow?

  • What does the standard say about this?
    From the assembly code produced, I see the compiler writes in the stack in the loop, like a normal array, but I cannot find anything about the standard behaviour.

starball
  • 20,030
  • 7
  • 43
  • 238
BiagioF
  • 9,368
  • 2
  • 26
  • 50

2 Answers2

19

Why does the compiler accept that declaration?

Because its authors chose to make it do so.

GCC in particular allows, by default, a lot of non-standard stuff that was historically accepted by old C compilers. They like "compatibility" in that sense.

What does the standard say about this?

The C++ grammar contains the following rule for array declarations in [dcl.array]:

In a declaration T D where D has the form
     D1 [ constant-expressionopt ] attribute-specifier-seqopt

[...] the type of the declarator-id in D is "derived-declarator-type-list array of N T"

In simple terms, this means that only a constant expression can be used to specify the size of an array. In your example, n is not a constant expression.

C++ does not have VLAs.

Where you see one being accepted, it is a compiler extension; to find out how that compiler implements such an extension, you would have to ask the compiler's authors (or examine its source, if applicable).

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 9
    "Forbid" is a bit strong. In general, the standard does not forbid extensions. As long as an implementation correctly handles correctly formed programs and issues *required* diagnostics, it is a compliant implementation. If the implementation also provides reproducible behaviour for cetain ill-formed programs, it is still just as compliant; the standard does not care about ill-formed programs. – rici Sep 05 '16 at 19:13
  • @rici Tell that to the GCC devs! _"the standard does not care about ill-formed programs"_ It does! It just doesn't mandate that they fail translation. This "extensions are allowed" all stems from that leniency. – Lightness Races in Orbit Sep 05 '16 at 19:14
  • In what way does my statement differ from the behaviour of gcc? I think the leniency is entirely appropriate; it allows compilers to implement and test proposed additions to the language, something which both gcc and clang devs do. (And how does the standard express its concern about ill-formed programs? It suffices with labelling them as ill-formed and explicitly not defining their behaviour.) – rici Sep 05 '16 at 19:38
  • 1
    @rici: The warning message says "ISO C++ forbids variable length arrays". You say "the standard does not forbid extensions". I can't elaborate further on how the two assertions differ without delving into quite basic reading comprehension, which I'm sure you do not require :) – Lightness Races in Orbit Sep 05 '16 at 19:39
  • _"And how does the standard express its concern about ill-formed programs? It suffices with labelling them as ill-formed and explicitly not defining their behaviour."_ Yes, that is how it manifests its concern. If it did not care, it would not even mention them. – Lightness Races in Orbit Sep 05 '16 at 19:40
  • You're right, I should file a bug :-) wrt concern, if I say "I couldn't give a rat's a.. about X, he can do what he bloody well wants", would you the argue that "rici doesn't care about X" is incorrect simply because I bothered to name him? Some shrinks might agree, I guess... – rici Sep 05 '16 at 19:50
  • On top of allowing VLAs in GCC, they actually *just* extended the functionality (as I [discovered recently](http://stackoverflow.com/a/33571722/472647)). – CodeMouse92 Sep 08 '16 at 00:36
  • An easy way to get GCC to adhere more closely to the standard and not allow most extensions is to pass (for example) `-std=c++17` rather than just using the default of `-std=gnu++17` (default language version of course changes with compiler version, but the point is, use `-std=c++...` rather than relying on the default or explicitly passing `-std=gnu++...` which enables language extensions). The same goes for the clang compiler btw. – Jesper Juhl May 29 '23 at 00:07
5

The standard requires that a conforming compiler must "issue a diagnostic" when it encounters something that is illegal. Having done that, it's free to continue to compile the code with an implementation-specific meaning. (Note that "with an implementation-specific meaning" is a polite form of "with undefined behavior").

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • @nobar -- the standard does not say what the code does, and it does not require the implementation to document what it does. That's "undefined behavior". Exactly. – Pete Becker Sep 25 '19 at 18:36
  • 1
    If there is UB and the compiler decides to document precisely what code it emits in that case, it effectively turns into implementation defined behavior on that platform: You can safely use it on this platform, but the code won't be portable to other platforms anymore. Just like you had relied on `sizeof(int) == 4`. – cmaster - reinstate monica Sep 14 '20 at 13:29