Skip to content

Commit f6947eb

Browse files
authored
Fix #671: Missing newline at end of file should produce a warning (#672)
1 parent 178f363 commit f6947eb

5 files changed

Lines changed: 142 additions & 52 deletions

File tree

integration_test.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def __test_relative_header_create_header(dir, with_pragma_once=True):
1717
#error header_was_already_included
1818
#endif
1919
const int dummy = 1;
20-
""")
20+
"""'\n')
2121
return header_file, "error: #error header_was_already_included"
2222

2323
def __test_relative_header_create_source(dir, include1, include2, is_include1_sys=False, is_include2_sys=False, inv=False):
@@ -31,7 +31,7 @@ def __test_relative_header_create_source(dir, include1, include2, is_include1_sy
3131
#undef TEST_H_INCLUDED
3232
#include {format_include(include1, is_include1_sys)}
3333
#include {format_include(include2, is_include2_sys)}
34-
""")
34+
"""'\n')
3535
return src_file
3636

3737
@pytest.mark.parametrize("with_pragma_once", (False, True))
@@ -201,27 +201,27 @@ def test_same_name_header(record_property, tmpdir):
201201
#include <header_a.h>
202202
#include <header_b.h>
203203
TEST
204-
""")
204+
"""'\n')
205205

206206
with open(header_a, "wt") as f:
207207
f.write("""
208208
#include "same_name.h"
209-
""")
209+
"""'\n')
210210

211211
with open(header_b, "wt") as f:
212212
f.write("""
213213
#include "same_name.h"
214-
""")
214+
"""'\n')
215215

216216
with open(same_name_a, "wt") as f:
217217
f.write("""
218218
#define TEST E
219-
""")
219+
"""'\n')
220220

221221
with open(same_name_b, "wt") as f:
222222
f.write("""
223223
#define TEST OK
224-
""")
224+
"""'\n')
225225

226226
args = [
227227
format_include_path_arg(include_a),
@@ -279,13 +279,13 @@ def test_pragma_once_matching(record_property, tmpdir):
279279
for n in names_to_test:
280280
f.write(f"""
281281
#include {n}
282-
""");
282+
"""'\n');
283283

284284
with open(once_header, "wt") as f:
285285
f.write(f"""
286286
#pragma once
287287
ONCE
288-
""");
288+
"""'\n');
289289

290290
args = [
291291
format_include_path_arg(test_dir),
@@ -463,7 +463,7 @@ def test_include_header_twice(tmpdir):
463463
#ifdef BBB
464464
# error BBB is defined
465465
#endif
466-
""")
466+
"""'\n')
467467

468468
test_file = os.path.join(tmpdir, 'test.c')
469469
with open(test_file, 'wt') as f:
@@ -473,7 +473,7 @@ def test_include_header_twice(tmpdir):
473473
474474
# define BBB
475475
# include "test.h"
476-
""")
476+
"""'\n')
477477

478478
args = [test_file]
479479

@@ -507,7 +507,7 @@ def test_define(record_property, tmpdir): # #589
507507
def test_utf16_bom(tmpdir):
508508
test_file = os.path.join(tmpdir, "test.cpp")
509509
with open(test_file, 'wb') as f:
510-
f.write(b'\xFF\xFE\x3B\x00')
510+
f.write(b'\xFF\xFE\x3B\x00\x0A\x00')
511511

512512
args = [test_file]
513513

main.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,14 @@ int main(int argc, char **argv)
278278
case simplecpp::Output::PORTABILITY_BACKSLASH:
279279
std::cerr << "portability: ";
280280
break;
281+
case simplecpp::Output::PORTABILITY_NO_EOF_NEWLINE:
282+
if (simplecpp::getCStd(dui.std) == simplecpp::CUnknown) {
283+
// Only UB for c code, suppress for c++ code
284+
// If no standard is specified then prefer to have a false negative
285+
continue;
286+
}
287+
std::cerr << "portability: ";
288+
break;
281289
case simplecpp::Output::UNHANDLED_CHAR_ERROR:
282290
std::cerr << "unhandled char error: ";
283291
break;

simplecpp.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ static const std::string COMMENT_END("*/");
662662
void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename, OutputList *outputList)
663663
{
664664
unsigned int multiline = 0U;
665+
bool trailing_nl = true;
665666

666667
const Token *oldLastToken = nullptr;
667668

@@ -671,6 +672,8 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename,
671672
if (!stream.good())
672673
break;
673674

675+
trailing_nl = false;
676+
674677
if (ch >= 0x80) {
675678
if (outputList) {
676679
simplecpp::Output err{
@@ -693,6 +696,7 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename,
693696
} else {
694697
location.line += multiline + 1;
695698
multiline = 0U;
699+
trailing_nl = true;
696700
}
697701
if (!multiline)
698702
location.col = 1;
@@ -961,6 +965,15 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename,
961965
location.adjust(currentToken);
962966
}
963967

968+
if (!trailing_nl && outputList) {
969+
Output err{
970+
Output::PORTABILITY_NO_EOF_NEWLINE,
971+
location,
972+
"No newline at end of file."
973+
};
974+
outputList->emplace_back(std::move(err));
975+
}
976+
964977
combineOperators();
965978
}
966979

simplecpp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ namespace simplecpp {
249249
SYNTAX_ERROR,
250250
DIRECTIVE_AS_MACRO_PARAMETER,
251251
PORTABILITY_BACKSLASH,
252+
PORTABILITY_NO_EOF_NEWLINE,
252253
UNHANDLED_CHAR_ERROR,
253254
EXPLICIT_INCLUDE_NOT_FOUND,
254255
FILE_NOT_FOUND,

0 commit comments

Comments
 (0)