Skip to content

Commit b8e2338

Browse files
committed
Compiler: add auto_func function parameter attribute
* add `auto_func` function parameter attribute * reject invalid combinations of `auto_xxx` attributes * fix tests
1 parent 15dc084 commit b8e2338

File tree

11 files changed

+81
-21
lines changed

11 files changed

+81
-21
lines changed

analyser/module_analyser_function.c2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ fn void Analyser.analyseFunction(Analyser* ma, FunctionDecl* fd) {
9999
if (v.hasAttrAutoLine() && !ref.isU32()) { // check for 'u32'
100100
ma.error(ref.getLoc(), "attribute 'auto_line' requires a parameter of type 'u32'");
101101
}
102+
if (v.hasAttrAutoFunc() && !ref.isConstCharPtr()) { // check for 'const char *'
103+
ma.error(ref.getLoc(), "attribute 'auto_func' requires a parameter of type 'const char*'");
104+
}
102105
}
103106

104107
if (v.hasPrintfFormat()) {

ast/qualtype.c2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public fn u32 QualType.getBitFieldWidth(const QualType* qt) {
9797
return bi.getBitfieldSize();
9898
}
9999
if (t.isEnumType()) {
100+
// TODO return bits needed for max value to allow use in bitfields
100101
EnumType* et = (EnumType*)t;
101102
QualType impl = et.getImplType();
102103
return impl.getBitFieldWidth();

ast/var_decl.c2

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ const char*[] varDeclNames = {
3535

3636
static_assert(elemsof(VarDeclKind), elemsof(varDeclNames));
3737

38+
type AutoAttr enum u32 {
39+
None,
40+
File,
41+
Line,
42+
Func,
43+
}
44+
3845
type VarDeclBits struct {
3946
u32 : NumDeclBits;
4047
u32 kind : 3;
@@ -43,8 +50,7 @@ type VarDeclBits struct {
4350
u32 has_init_call : 1; // local variables only
4451
u32 attr_weak : 1; // globals only
4552
u32 addr_used : 1;
46-
u32 auto_file : 1; // for parameters only
47-
u32 auto_line : 1; // for parameters only
53+
u32 auto_attr : 2; // AutoAttr, for parameters only
4854
u32 printf_format : 1; // for parameters only
4955
}
5056

@@ -247,23 +253,31 @@ public fn bool VarDecl.hasAttrWeak(const VarDecl* d) {
247253
}
248254

249255
public fn void VarDecl.setAttrAutoFile(VarDecl* d) {
250-
d.base.varDeclBits.auto_file = 1;
256+
d.base.varDeclBits.auto_attr = AutoAttr.File;
251257
}
252258

253259
public fn bool VarDecl.hasAttrAutoFile(const VarDecl* d) {
254-
return d.base.varDeclBits.auto_file;
260+
return d.base.varDeclBits.auto_attr == AutoAttr.File;
255261
}
256262

257263
public fn void VarDecl.setAttrAutoLine(VarDecl* d) {
258-
d.base.varDeclBits.auto_line = 1;
264+
d.base.varDeclBits.auto_attr = AutoAttr.Line;
259265
}
260266

261267
public fn bool VarDecl.hasAttrAutoLine(const VarDecl* d) {
262-
return d.base.varDeclBits.auto_line;
268+
return d.base.varDeclBits.auto_attr == AutoAttr.Line;
269+
}
270+
271+
public fn void VarDecl.setAttrAutoFunc(VarDecl* d) {
272+
d.base.varDeclBits.auto_attr = AutoAttr.Func;
273+
}
274+
275+
public fn bool VarDecl.hasAttrAutoFunc(const VarDecl* d) {
276+
return d.base.varDeclBits.auto_attr == AutoAttr.Func;
263277
}
264278

265279
public fn bool VarDecl.hasAutoAttr(const VarDecl* d) {
266-
return d.base.varDeclBits.auto_file || d.base.varDeclBits.auto_line;
280+
return d.base.varDeclBits.auto_attr != AutoAttr.None;
267281
}
268282

269283
public fn void VarDecl.setPrintfFormat(VarDecl* d) {
@@ -289,8 +303,12 @@ fn void VarDecl.print(const VarDecl* d, string_buffer.Buf* out, u32 indent) {
289303
if (d.hasLocalQualifier()) out.add(" (local)");
290304
if (d.base.varDeclBits.attr_weak) out.add(" weak");
291305
if (d.base.varDeclBits.addr_used) out.add(" addr_used");
292-
if (d.base.varDeclBits.auto_file) out.add(" auto_file");
293-
if (d.base.varDeclBits.auto_line) out.add(" auto_line");
306+
switch ((AutoAttr)d.base.varDeclBits.auto_attr) {
307+
case None: break;
308+
case File: out.add(" auto_file"); break;
309+
case Line: out.add(" auto_line"); break;
310+
case Func: out.add(" auto_func"); break;
311+
}
294312
if (d.base.varDeclBits.printf_format) out.add(" printf_format");
295313
if (d.base.varDeclBits.has_init_call) out.add(" init_call");
296314
d.base.printBits(out);

ast_utils/attr.c2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public type AttrKind enum u8 {
4040
Pure, // Func
4141
AutoFile, // Var, function param only
4242
AutoLine, // Var, function param only
43+
AutoFunc, // Var, function param only
4344
}
4445

4546
const char*[] attrKind_names = {
@@ -63,6 +64,7 @@ const char*[] attrKind_names = {
6364
"pure",
6465
"auto_file",
6566
"auto_line",
67+
"auto_func",
6668
}
6769

6870
static_assert(elemsof(AttrKind), elemsof(attrKind_names));
@@ -140,6 +142,7 @@ const AttrReq[] Required_arg = {
140142
[AttrKind.Pure] = AttrReq.NoArg,
141143
[AttrKind.AutoFile] = AttrReq.NoArg,
142144
[AttrKind.AutoLine] = AttrReq.NoArg,
145+
[AttrKind.AutoFunc] = AttrReq.NoArg,
143146
}
144147
static_assert(elemsof(AttrKind), elemsof(Required_arg));
145148

generator/c/c2i_generator_decl.c2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ fn void Generator.emitVarDecl(Generator* gen, const Decl* d, u32 indent) {
6969
if (v.hasAutoAttr()) {
7070
if (v.hasAttrAutoFile()) out.add(" @(auto_file)");
7171
if (v.hasAttrAutoLine()) out.add(" @(auto_line)");
72+
if (v.hasAttrAutoFunc()) out.add(" @(auto_func)");
7273
}
7374
// Note: dont add ';' because it could also be a function argument
7475
}

generator/c/c_generator_call.c2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ fn void Generator.emitCall(Generator* gen, string_buffer.Buf* out, Expr* e) {
137137
if (vd.hasAttrAutoLine()) {
138138
out.print("%d", loc.line);
139139
}
140+
if (vd.hasAttrAutoFunc()) {
141+
out.print("\"%s\"", gen.cur_function.asDecl().getFullName());
142+
}
140143
needs_comma = true;
141144
func_index++;
142145
continue;

parser/ast_builder.c2

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -523,30 +523,41 @@ fn void Builder.actOnVarAttr(Builder* b, Decl* d, const Attr* a) {
523523
}
524524
}
525525

526-
public fn void Builder.actOnParamAttr(Builder* b,
526+
public fn bool Builder.actOnParamAttr(Builder* b,
527527
VarDecl* d,
528528
u32 name,
529529
SrcLoc loc)
530530
{
531531
AttrKind kind = attr.find(name);
532532
switch (kind) {
533533
case Unknown:
534+
// TODO should be a warning
534535
b.diags.error(loc, "unknown attribute '%s'", ast.idx2name(name));
535-
break;
536+
return false;
536537
case PrintfFormat:
537538
d.setPrintfFormat();
538-
break;
539+
return true;
539540
case AutoFile:
541+
if (d.hasAutoAttr()) goto invalid;
540542
d.setAttrAutoFile();
541-
break;
543+
return true;
542544
case AutoLine:
545+
if (d.hasAutoAttr()) goto invalid;
543546
d.setAttrAutoLine();
544-
break;
547+
return true;
548+
case AutoFunc:
549+
if (d.hasAutoAttr()) goto invalid;
550+
d.setAttrAutoFunc();
551+
return true;
552+
invalid:
553+
b.diags.error(loc, "invalid combination of attributes");
554+
return false;
545555
default:
546556
b.diags.error(loc, "attribute '%s' cannot be applied to function parameters",
547-
ast.idx2name(name));
548-
break;
557+
ast.idx2name(name));
558+
return false;
549559
}
560+
return false;
550561
}
551562

552563
public fn void Builder.actOnAttr(Builder* b, attr.Attr* a) {

parser/c2_parser.c2

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ fn void Parser.parseParamOptionalAttributes(Parser* p, VarDecl* d) {
367367

368368
p.expectAndConsume(Kind.LParen);
369369

370+
bool has_error = false;
370371
while (1) {
371372
p.expectIdentifier();
372373
u32 attr_id = p.tok.name_idx;
@@ -376,9 +377,9 @@ fn void Parser.parseParamOptionalAttributes(Parser* p, VarDecl* d) {
376377
if (p.tok.kind == Kind.Equal) {
377378
p.error("a parameter attribute cannot have a value");
378379
}
379-
380-
p.builder.actOnParamAttr(d, attr_id, loc);
381-
380+
if (!has_error) {
381+
has_error = !p.builder.actOnParamAttr(d, attr_id, loc);
382+
}
382383
if (p.tok.kind != Kind.Comma) break;
383384
p.consumeToken();
384385
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// @warnings{no-unused}
2+
module test;
3+
4+
// These errors occur at analyse time
5+
fn void log5(u32 line @(auto_file)) { // @error{attribute 'auto_file' requires a parameter of type 'const char*'}
6+
}
7+
8+
fn void log6(const char* line @(auto_line)) { // @error{attribute 'auto_line' requires a parameter of type 'u32'}
9+
}
10+
11+
fn void log7(u32 line @(auto_func)) { // @error{attribute 'auto_func' requires a parameter of type 'const char*'}
12+
}

test/auto_args/auto_arg_both.c2

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
// @warnings{no-unused}
22
module test;
33

4-
fn void log1(u32 line @(auto_line, auto_file)) { // @error{attribute 'auto_file' requires a parameter of type 'const char*'}
4+
// These errors occur at parse time
5+
fn void log1(u32 line @(auto_line, auto_file)) { // @error{invalid combination of attributes}
56
}
67

7-
fn void log2(const char* line @(auto_line, auto_file)) { // @error{attribute 'auto_line' requires a parameter of type 'u32'}
8+
fn void log2(const char* line @(auto_line, auto_file)) { // @error{invalid combination of attributes}
89
}
910

11+
fn void log3(const char* line @(auto_file, auto_func)) { // @error{invalid combination of attributes}
12+
}
13+
14+
fn void log4(const char* line @(auto_file, auto_line, auto_func)) { // @error{invalid combination of attributes}
15+
}

0 commit comments

Comments
 (0)