diff --git a/src/Diagnostics.zig b/src/Diagnostics.zig index fa9405e6..5adbdcdb 100644 --- a/src/Diagnostics.zig +++ b/src/Diagnostics.zig @@ -120,6 +120,7 @@ pub const Options = packed struct { @"gnu-binary-literal": Kind = .default, @"variadic-macros": Kind = .default, varargs: Kind = .default, + @"#warnings": Kind = .default, }; const messages = struct { @@ -133,6 +134,12 @@ const messages = struct { const extra = .str; const kind = .@"error"; }; + const warning_directive = struct { + const msg = "{s}"; + const opt = "#warnings"; + const extra = .str; + const kind = .@"warning"; + }; const elif_without_if = struct { const msg = "#elif without #if"; const kind = .@"error"; diff --git a/src/Preprocessor.zig b/src/Preprocessor.zig index cc87fef0..7a6f82bc 100644 --- a/src/Preprocessor.zig +++ b/src/Preprocessor.zig @@ -203,7 +203,6 @@ fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { .comp = pp.comp, .source = source.id, }; - const TRAILING_WS = " \r\t\x0B\x0C"; // Estimate how many new tokens this source will contain. const estimated_token_count = source.buf.len / 8; @@ -222,18 +221,26 @@ fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { .hash => if (start_of_line) { const directive = tokenizer.nextNoWS(); switch (directive.id) { - .keyword_error => { + .keyword_error, .keyword_warning => { // #error tokens.. - const start = tokenizer.index; - while (tokenizer.index < tokenizer.buf.len) : (tokenizer.index += 1) { - if (tokenizer.buf[tokenizer.index] == '\n') break; + pp.top_expansion_buf.items.len = 0; + const char_top = pp.char_buf.items.len; + defer pp.char_buf.items.len = char_top; + + while (true) { + tok = tokenizer.next(); + if (tok.id == .nl or tok.id == .eof) break; + if (tok.id == .whitespace) tok.id = .macro_ws; + try pp.top_expansion_buf.append(tokFromRaw(tok)); } - var slice = tokenizer.buf[start..tokenizer.index]; - slice = mem.trim(u8, slice, TRAILING_WS); + try pp.stringify(pp.top_expansion_buf.items); + const slice = pp.char_buf.items[char_top + 1 .. pp.char_buf.items.len - 2]; + const duped = try pp.comp.diag.arena.allocator().dupe(u8, slice); + try pp.comp.diag.add(.{ - .tag = .error_directive, - .loc = .{ .id = tok.source, .byte_offset = tok.start, .line = directive.line }, - .extra = .{ .str = slice }, + .tag = if (directive.id == .keyword_error) .error_directive else .warning_directive, + .loc = .{ .id = tok.source, .byte_offset = directive.start, .line = directive.line }, + .extra = .{ .str = duped }, }, &.{}); }, .keyword_if => { @@ -359,7 +366,7 @@ fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { }, else => { try pp.err(tok, .invalid_preprocessing_directive); - try pp.expectNl(&tokenizer); + skipToNl(&tokenizer); }, } }, diff --git a/src/Tokenizer.zig b/src/Tokenizer.zig index 41138423..008e09b3 100644 --- a/src/Tokenizer.zig +++ b/src/Tokenizer.zig @@ -211,6 +211,7 @@ pub const Token = struct { keyword_elif, keyword_endif, keyword_error, + keyword_warning, keyword_pragma, keyword_line, keyword_va_args, @@ -250,6 +251,7 @@ pub const Token = struct { .keyword_elif, .keyword_endif, .keyword_error, + .keyword_warning, .keyword_pragma, .keyword_line, .keyword_va_args, @@ -340,6 +342,7 @@ pub const Token = struct { .keyword_elif, .keyword_endif, .keyword_error, + .keyword_warning, .keyword_pragma, .keyword_line, .keyword_va_args, @@ -508,6 +511,7 @@ pub const Token = struct { .keyword_elif => "elif", .keyword_endif => "endif", .keyword_error => "error", + .keyword_warning => "warning", .keyword_pragma => "pragma", .keyword_line => "line", .keyword_va_args => "__VA_ARGS__", @@ -715,6 +719,7 @@ pub const Token = struct { .{ "elif", .keyword_elif }, .{ "endif", .keyword_endif }, .{ "error", .keyword_error }, + .{ "warning", .keyword_warning }, .{ "pragma", .keyword_pragma }, .{ "line", .keyword_line }, .{ "__VA_ARGS__", .keyword_va_args }, diff --git a/test/cases/__has_attribute.c b/test/cases/__has_attribute.c index 5aae9387..803d182e 100644 --- a/test/cases/__has_attribute.c +++ b/test/cases/__has_attribute.c @@ -7,4 +7,4 @@ # endif #endif -#define EXPECTED_ERRORS "__has_attribute.c:3:7: error: attribute exists" +#define EXPECTED_ERRORS "__has_attribute.c:3:8: error: attribute exists" diff --git a/test/cases/__has_builtin.c b/test/cases/__has_builtin.c index 8150c540..6613c8b3 100644 --- a/test/cases/__has_builtin.c +++ b/test/cases/__has_builtin.c @@ -7,4 +7,4 @@ # endif #endif -#define EXPECTED_ERRORS "__has_builtin.c:3:7: error: builtin exists" +#define EXPECTED_ERRORS "__has_builtin.c:3:8: error: builtin exists" diff --git a/test/cases/__has_extension.c b/test/cases/__has_extension.c index bc11f174..454263ac 100644 --- a/test/cases/__has_extension.c +++ b/test/cases/__has_extension.c @@ -7,4 +7,4 @@ # endif #endif -#define EXPECTED_ERRORS "__has_extension.c:3:7: error: extension exists" +#define EXPECTED_ERRORS "__has_extension.c:3:8: error: extension exists" diff --git a/test/cases/__has_feature.c b/test/cases/__has_feature.c index 1881bfe9..fcad2c82 100644 --- a/test/cases/__has_feature.c +++ b/test/cases/__has_feature.c @@ -7,4 +7,4 @@ # endif #endif -#define EXPECTED_ERRORS "__has_feature.c:3:7: error: feature exists" +#define EXPECTED_ERRORS "__has_feature.c:3:8: error: feature exists" diff --git a/test/cases/pragma warning and error.c b/test/cases/pragma warning and error.c index 02aa90c4..0497a29e 100644 --- a/test/cases/pragma warning and error.c +++ b/test/cases/pragma warning and error.c @@ -26,6 +26,9 @@ foo(bar 1) foo(baz 2) +#warning foo \ +bar + #define EXPECTED_ERRORS "pragma warning and error.c:3:13: error: pragma warning requires string literal" \ "pragma warning and error.c:5:13: error: pragma warning requires string literal" \ "pragma warning and error.c:7:13: warning: A warning [-W#pragma-messages]" \ @@ -36,3 +39,4 @@ foo(baz 2) "pragma warning and error.c:17:13: error: Another error" \ "pragma warning and error.c:26:1: note: #pragma message: bar 1" \ "pragma warning and error.c:27:1: note: #pragma message: baz 2" \ + "pragma warning and error.c:29:2: warning: foo bar [-W#warnings]" \