Reputation: 34608
From C11 5.1.1.2 Translation phases:
Paragraph 2:
[...] A source file that is not empty shall end in a new-line character, which shall not be immediately preceded by a backslash character before any such splicing takes place.
It means every source file must end with a newline.
Example:
#include <stdio.h>
int main()
{
printf("Hello world\n");
return 0;
}
Above example compiled on Clang using clang prog.c -Wall -Wextra -std=gnu11 -pedantic
command. The compiler generates following warning:
prog.c:7:16: warning: no newline at end of file [-Wnewline-eof]
}
^
It's ok because there is no newline at the end of the source file.
Using gcc prog.c -Wall -Wextra -std=gnu11 -pedantic
command, I compiled the above program on GCC. GCC doesn't generate any warning or error.
So, Why doesn't GCC generate any warning or error?
Upvotes: 5
Views: 1992
Reputation: 213892
I believe gcc is non-conforming.
Regardless of how one may reason about the part in 5.1.1.2 not being a constraint, gcc also allows this non-conforming program:
#include <stdio.h> /* no new line here */
This is a pre-processing directive. C17 6.10 §2 defines a pre-processing directive as (bold emphasis mine):
A preprocessing directive consists of a sequence of preprocessing tokens that satisfies the following constraints: The first token in the sequence is a
#
preprocessing token that (at the start of translation phase 4) is either the first character in the source file (optionally after white space containing no new-line characters) or that follows white space containing at least one new-line character. The last token in the sequence is the first newline character that follows the first token in the sequence. A new-line character ends the preprocessing directive even if it occurs within what would otherwise be an invocation of a function-like macro.
Furthermore 6.10 §5
Constraints
The only white-space characters that shall appear between preprocessing tokens within a preprocessing directive (from just after the introducing#
preprocessing token through just before the terminating new-line character) ...
This text is supported by formal syntax in 6.10:
control-line:
# include
pp-tokens new-line
new-line:
the new-line character
An implementation is required to issue a diagnostic message in this situation:
5.1.1.3 Diagnostics
A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, ...
Silently allowing #include <stdio.h> /* no new line here */
without any diagnostic even in -pedantic
mode renders gcc non-conforming since there is (arguably) a constraint violation of 6.10 §5 as well as definitely a syntax rule violation of the syntax listed in 6.10.
The clang compiler behaves correctly.
Upvotes: 2
Reputation: 12668
There's a problem, newlines are not well standard defined, as different systems have different new line conventions. But you are right... if the standard says a compiler must emit a warning in that case and gcc doesn't, it should be filed as a noncomplianance issue.
But I agree with @supercat's answer, in the sense that it can be assumed that a file without a final \n
can be safely interpreted as a properly delimited text file with no line ending at the end... as the \n
can be interpreted as a line separator character, and not a line ending one. In case this interpretation is valid, an empty file would be parsed as a one empty line file with no problem for the compiler to parse it, and no warning should be issued in that case. The same applies to any file without a final \n
, and a file finished with a \n
should be interpreted as a n + 1
lines file, with an extra empty line (this doesn't make any difference to the meaning of the C code inside, I'm afraid)
This will be probably the response you'll get in case you go to the gcc project to complain, so be prudent, but don't hesitate and do it.
By the way, have you tried to feed the compiler with a final \\
character (without a \n
char) the compiler is allowed to insert the final newline to simulate a properly defined file, but the preprocessor has to deal in a special form in case a \\
character is followed by a new line. In that case, the compiler should emit something, as you cannot continue past the last line of the file. Clang doesn't say anything in case the last line terminates in a \\
(that is a nonconformance) let's see what does gcc.... (sorry, I have no access to a gcc by now)
Upvotes: 1
Reputation: 81169
The Standard does not specify any particular relationship between physical bytes stored on disk and the logical characters that make up a C program. If the source character set only uses codes 0x00-0x7E, for example, a conforming implementation might say that the first character of any line will have the upper bit set while foregoing any other kind of delimiter. Such an implementation would then be required to behave as though each line were followed by a newline character, even though no newline characters would appear in the source file (I don't think implementations are required to allow source lines that are completely blank to be represented in a way distinguishable from lines containing a single blank character).
If an implementation specifies that a text file consists of a number of lines separated by newline characters, and that an N-line file will contain N-1 newlines, it would be required to behave as though there was a newline character following the last byte in the file. If, however, the implementation specified that all valid text files end with a newline, it would be under no obligation when given an invalid text file that doesn't.
Note that, among other things, it's plausible that on some implementations, the first line following a #include
will be concatenated to an incomplete line at the end of an included file. Such behavior, while quirky, might be useful in some cases and it's possible some code may have relied upon it. Given that such splicing, if unexpected, could have essentially unbounded consequences, leaving the behavior as Undefined is simpler than trying to categorize what might happen.
Upvotes: 2
Reputation: 141608
The meaning of "shall" is defined by section 4 point 2:
If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined.
The passage you quoted is not in a Constraints section. Therefore, if the source file does not end in a trailing newline then the program has undefined behaviour.
No diagnostic is required for undefined behaviour. The compiler is free to do anything. The GCC developers have probably decided to make the program behave as if there were a newline on the end and not bother the user with a warning.
Upvotes: 4