Skip to content

Commit

Permalink
Preprocessor: implement __has_c_attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
Vexu committed Nov 6, 2023
1 parent 75d5b44 commit 0b621ed
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/Preprocessor.zig
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ const builtin_macros = struct {
.id = .macro_param_has_attribute,
.source = .generated,
}};
const has_c_attribute = [1]RawToken{.{
.id = .macro_param_has_c_attribute,
.source = .generated,
}};
const has_declspec_attribute = [1]RawToken{.{
.id = .macro_param_has_declspec_attribute,
.source = .generated,
Expand Down Expand Up @@ -189,6 +193,7 @@ fn addBuiltinMacro(pp: *Preprocessor, name: []const u8, is_func: bool, tokens: [

pub fn addBuiltinMacros(pp: *Preprocessor) !void {
try pp.addBuiltinMacro("__has_attribute", true, &builtin_macros.has_attribute);
try pp.addBuiltinMacro("__has_c_attribute", true, &builtin_macros.has_c_attribute);
try pp.addBuiltinMacro("__has_declspec_attribute", true, &builtin_macros.has_declspec_attribute);
try pp.addBuiltinMacro("__has_warning", true, &builtin_macros.has_warning);
try pp.addBuiltinMacro("__has_feature", true, &builtin_macros.has_feature);
Expand Down Expand Up @@ -1514,6 +1519,53 @@ fn expandFuncMacro(
try pp.comp.generated_buf.writer().print("{}\n", .{@intFromBool(result)});
try buf.append(try pp.makeGeneratedToken(start, .pp_num, tokFromRaw(raw)));
},
.macro_param_has_c_attribute => {
const arg = expanded_args.items[0];
const not_found = "0\n";
const result = if (arg.len == 0) blk: {
const extra = Diagnostics.Message.Extra{ .arguments = .{ .expected = 1, .actual = 0 } };
try pp.comp.diag.add(.{ .tag = .expected_arguments, .loc = loc, .extra = extra }, &.{});
break :blk not_found;
} else res: {
var invalid: ?Token = null;
var identifier: ?Token = null;
for (arg) |tok| {
if (tok.id == .macro_ws) continue;
if (tok.id == .comment) continue;
if (!tok.id.isMacroIdentifier()) {
invalid = tok;
break;
}
if (identifier) |_| invalid = tok else identifier = tok;
}
if (identifier == null and invalid == null) invalid = .{ .id = .eof, .loc = loc };
if (invalid) |some| {
try pp.comp.diag.add(
.{ .tag = .feature_check_requires_identifier, .loc = some.loc },
some.expansionSlice(),
);
break :res not_found;
}
if (!pp.comp.langopts.standard.atLeast(.c2x)) break :res not_found;

const attrs = std.ComptimeStringMap([]const u8, .{
.{ "deprecated", "201904L\n" },
.{ "fallthrough", "201904L\n" },
.{ "maybe_unused", "201904L\n" },
.{ "nodiscard", "202003L\n" },
.{ "noreturn", "202202L\n" },
.{ "_Noreturn", "202202L\n" },
.{ "unsequenced", "202207L\n" },
.{ "reproducible", "202207L\n" },
});

const ident_str = pp.expandedSlice(identifier.?);
break :res attrs.get(ident_str) orelse not_found;
};
const start = pp.comp.generated_buf.items.len;
try pp.comp.generated_buf.appendSlice(result);
try buf.append(try pp.makeGeneratedToken(start, .pp_num, tokFromRaw(raw)));
},
.macro_param_pragma_operator => {
const param_toks = expanded_args.items[0];
// Clang and GCC require exactly one token (so, no parentheses or string pasting)
Expand Down
3 changes: 3 additions & 0 deletions src/Tokenizer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ pub const Token = struct {
macro_ws,
/// Special token for implementing __has_attribute
macro_param_has_attribute,
/// Special token for implementing __has_c_attribute
macro_param_has_c_attribute,
/// Special token for implementing __has_declspec_attribute
macro_param_has_declspec_attribute,
/// Special token for implementing __has_warning
Expand Down Expand Up @@ -521,6 +523,7 @@ pub const Token = struct {
.stringify_param,
.stringify_va_args,
.macro_param_has_attribute,
.macro_param_has_c_attribute,
.macro_param_has_declspec_attribute,
.macro_param_has_warning,
.macro_param_has_feature,
Expand Down
11 changes: 11 additions & 0 deletions test/cases/__has_c_attribute.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//aro-args -std=c2x
#if defined __has_c_attribute
# if __has_c_attribute(fallthrough)
#error attribute exists
# endif
# if __has_c_attribute(does_not_exist)
#error attribute exists
# endif
#endif

#define EXPECTED_ERRORS "__has_c_attribute.c:4:8: error: attribute exists"

0 comments on commit 0b621ed

Please sign in to comment.