23

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.

4
  • You have asked two questions, not one. Commented Sep 5, 2016 at 16:27
  • 4
    Compiler extensions are just that. Extensions. Commented Sep 5, 2016 at 16:30
  • 5
    "producing just a warning in case -pedantic flag is enable." - which is all -pedantic promises. -pedantic-errors makes these errors instead. Commented Sep 5, 2016 at 16:41
  • "the compiler (g++ and clang++) accepts the code" - only in their default modes (which permit extensions) if you enable strict C++ conformance mode (which I'd recommend) the code is not accepted. For C++20, use -std=c++20 (the default is -std=gnu++20) and -pedantic. Commented Aug 26, 2023 at 5:11

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

7 Comments

"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 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.
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.)
"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.
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...
|
6

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

2 Comments

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.