Skip to content

Commit 9fc3310

Browse files
authored
[C2y] Implement WG14 N3411 (#130180)
This paper (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3411.pdf) allows a source file to end without a newline. Clang has supported this as a conforming extension for a long time, so this suppresses the diagnotic in C2y mode but continues to diagnose as an extension in earlier language modes. It also continues to diagnose if the user passes -Wnewline-eof explicitly.
1 parent 2c8b824 commit 9fc3310

File tree

4 files changed

+26
-9
lines changed

4 files changed

+26
-9
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ C Language Changes
111111

112112
C2y Feature Support
113113
^^^^^^^^^^^^^^^^^^^
114+
- Implemented N3411 which allows a source file to not end with a newline
115+
character. This is still reported as a conforming extension in earlier
116+
language modes.
114117

115118
C23 Feature Support
116119
^^^^^^^^^^^^^^^^^^^

clang/lib/Lex/Lexer.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3192,23 +3192,22 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
31923192
if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
31933193
DiagnosticsEngine &Diags = PP->getDiagnostics();
31943194
SourceLocation EndLoc = getSourceLocation(BufferEnd);
3195-
unsigned DiagID;
3195+
unsigned DiagID = diag::warn_no_newline_eof;
31963196

31973197
if (LangOpts.CPlusPlus11) {
31983198
// C++11 [lex.phases] 2.2 p2
31993199
// Prefer the C++98 pedantic compatibility warning over the generic,
32003200
// non-extension, user-requested "missing newline at EOF" warning.
3201-
if (!Diags.isIgnored(diag::warn_cxx98_compat_no_newline_eof, EndLoc)) {
3201+
if (!Diags.isIgnored(diag::warn_cxx98_compat_no_newline_eof, EndLoc))
32023202
DiagID = diag::warn_cxx98_compat_no_newline_eof;
3203-
} else {
3204-
DiagID = diag::warn_no_newline_eof;
3205-
}
32063203
} else {
3207-
DiagID = diag::ext_no_newline_eof;
3204+
// This is conforming in C2y, but is an extension in earlier language
3205+
// modes.
3206+
if (!LangOpts.C2y)
3207+
DiagID = diag::ext_no_newline_eof;
32083208
}
32093209

3210-
Diag(BufferEnd, DiagID)
3211-
<< FixItHint::CreateInsertion(EndLoc, "\n");
3210+
Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
32123211
}
32133212

32143213
BufferPtr = CurPtr;

clang/test/C/C2y/n3411.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang_cc1 -verify=good -std=c2y -Wall -pedantic %s
2+
// RUN: %clang_cc1 -verify -Wnewline-eof -std=c2y -Wall -pedantic %s
3+
// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s
4+
// RUN: %clang_cc1 -verify=good -std=c23 %s
5+
6+
/* WG14 N3411: Yes
7+
* Slay Some Earthly Demons XII
8+
*
9+
* Allow a non-empty source file to end without a final newline character. Note
10+
* that this file intentionally does not end with a trailing newline.
11+
*/
12+
// good-no-diagnostics
13+
14+
int x; // Ensure the file contains at least one declaration.
15+
// expected-warning {{no newline at end of file}}

clang/www/c_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ <h2 id="c2y">C2y implementation status</h2>
294294
<tr>
295295
<td>Slay Some Earthly Demons XII</td>
296296
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3411.pdf">N3411</a></td>
297-
<td class="unknown" align="center">Unknown</td>
297+
<td class="unreleased" align="center">Clang 21</td>
298298
</tr>
299299
<tr>
300300
<td>Slay Some Earthly Demons XIII</td>

0 commit comments

Comments
 (0)