Skip to content

Commit 9dcc91a

Browse files
authored
ImportC: Use the location of the declarator ident for dsymbols (dlang/dmd!21729)
The source location of variable and function declarations were all pointing at various odd places. - Functions were given the location of the opening `{`. - Parameters were given the location of the `,` separator. - Tag types such as typedefs or enum declaration were given the location of the closing `;` in the declaration. - Fields were given the location of the closing `;`. - Bitfields were given the location of the width expression. These now all point at the location of the declaration's identifier if one exists. For nameless parameters, the location points at the beginning of its type. Anonymous bitfields have a location pointing at the width expression.
1 parent e3c3a15 commit 9dcc91a

File tree

7 files changed

+51
-47
lines changed

7 files changed

+51
-47
lines changed

dmd/astcodegen.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct ASTCodegen
4242
alias UserAttributeDeclaration = dmd.attrib.UserAttributeDeclaration;
4343
alias Ensure = dmd.func.Ensure; // workaround for bug in older DMD frontends
4444
alias ErrorExp = dmd.expression.ErrorExp;
45+
alias ArgumentLabel = dmd.expression.ArgumentLabel;
4546

4647
alias MODFlags = dmd.mtype.MODFlags;
4748
alias Type = dmd.mtype.Type;

dmd/cparse.d

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,7 +1836,7 @@ final class CParser(AST) : Parser!AST
18361836
bool first = true;
18371837
while (1)
18381838
{
1839-
Identifier id;
1839+
AST.ArgumentLabel id;
18401840
AST.StringExp asmName;
18411841
auto dt = cparseDeclarator(DTR.xdirect_fd, tspec, id, specifier);
18421842
if (!dt)
@@ -1903,7 +1903,7 @@ final class CParser(AST) : Parser!AST
19031903
*/
19041904
auto t = &token;
19051905
if (first && // first declarator
1906-
id &&
1906+
id.name &&
19071907
dt.isTypeFunction() && // function type not inherited from a typedef
19081908
level == LVL.global && // function definitions only at global scope
19091909
t.value != TOK.endOfFile)
@@ -1949,12 +1949,12 @@ final class CParser(AST) : Parser!AST
19491949
Identifier idt;
19501950
if (auto tt = dt.isTypeTag())
19511951
{
1952-
if (!tt.id && id)
1952+
if (!tt.id && id.name)
19531953
/* This applies for enums declared as
19541954
* typedef enum {A} E;
19551955
* Or for similar structs and unions.
19561956
*/
1957-
tt.id = id;
1957+
tt.id = id.name;
19581958
if (tt.members)
19591959
{
19601960
Specifier spec;
@@ -1976,16 +1976,16 @@ final class CParser(AST) : Parser!AST
19761976
}
19771977
if (isalias)
19781978
{
1979-
//printf("AliasDeclaration %s %s\n", id.toChars(), dt.toChars());
1980-
auto ad = new AST.AliasDeclaration(token.loc, id, dt);
1981-
if (id == idt)
1979+
//printf("AliasDeclaration %s %s\n", id.name.toChars(), dt.toChars());
1980+
auto ad = new AST.AliasDeclaration(id.loc, id.name, dt);
1981+
if (id.name == idt)
19821982
ad.hidden = true; // do not print when generating .di files
19831983
s = ad;
19841984
}
19851985

1986-
insertTypedefToTypedefTab(id, dt); // remember typedefs
1986+
insertTypedefToTypedefTab(id.name, dt); // remember typedefs
19871987
}
1988-
else if (id)
1988+
else if (id.name)
19891989
{
19901990
if (auto tt = dt.isTypeTag())
19911991
{
@@ -2021,7 +2021,7 @@ final class CParser(AST) : Parser!AST
20212021
initializer = cparseInitializer();
20222022
}
20232023
// declare the symbol
2024-
assert(id);
2024+
assert(id.name);
20252025

20262026
if (isFunctionTypedef(dt))
20272027
{
@@ -2031,7 +2031,7 @@ final class CParser(AST) : Parser!AST
20312031
error("functions cannot be `_Thread_local`"); // C11 6.7.1-4
20322032
STC stc = specifiersToSTC(level, specifier);
20332033
stc &= ~STC.gshared; // no gshared functions
2034-
auto fd = new AST.FuncDeclaration(token.loc, Loc.initial, id, stc, dt, specifier.noreturn);
2034+
auto fd = new AST.FuncDeclaration(id.loc, Loc.initial, id.name, stc, dt, specifier.noreturn);
20352035
specifiersToFuncDeclaration(fd, specifier);
20362036
s = fd;
20372037
}
@@ -2042,12 +2042,12 @@ final class CParser(AST) : Parser!AST
20422042
if (!hasInitializer &&
20432043
!(specifier.scw & (SCW.xextern | SCW.xstatic | SCW.x_Thread_local) || level == LVL.global))
20442044
initializer = new AST.VoidInitializer(token.loc);
2045-
auto vd = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(level, specifier));
2045+
auto vd = new AST.VarDeclaration(id.loc, dt, id.name, initializer, specifiersToSTC(level, specifier));
20462046
specifiersToVarDeclaration(vd, specifier);
20472047
s = vd;
20482048
}
20492049
if (level != LVL.global)
2050-
insertIdToTypedefTab(id); // non-typedef declarations can hide typedefs in outer scopes
2050+
insertIdToTypedefTab(id.name); // non-typedef declarations can hide typedefs in outer scopes
20512051
}
20522052
if (s !is null)
20532053
{
@@ -2086,7 +2086,7 @@ final class CParser(AST) : Parser!AST
20862086
}
20872087
symbols.push(s);
20882088
}
2089-
if (level == LVL.global && !id)
2089+
if (level == LVL.global && !id.name)
20902090
error("expected identifier for declaration");
20912091

20922092
first = false;
@@ -2137,7 +2137,7 @@ final class CParser(AST) : Parser!AST
21372137
* Returns:
21382138
* Dsymbol for the function
21392139
*/
2140-
AST.Dsymbol cparseFunctionDefinition(Identifier id, AST.TypeFunction ft, ref Specifier specifier)
2140+
AST.Dsymbol cparseFunctionDefinition(AST.ArgumentLabel id, AST.TypeFunction ft, ref Specifier specifier)
21412141
{
21422142
/* Start function scope
21432143
*/
@@ -2218,12 +2218,12 @@ final class CParser(AST) : Parser!AST
22182218

22192219
STC stc = specifiersToSTC(LVL.global, specifier);
22202220
stc &= ~STC.gshared; // no gshared functions
2221-
auto fd = new AST.FuncDeclaration(locFunc, prevloc, id, stc, ft, specifier.noreturn);
2221+
auto fd = new AST.FuncDeclaration(id.loc, prevloc, id.name, stc, ft, specifier.noreturn);
22222222
specifiersToFuncDeclaration(fd, specifier);
22232223

22242224
if (addFuncName)
22252225
{
2226-
auto s = createFuncName(locFunc, id);
2226+
auto s = createFuncName(locFunc, id.name);
22272227
body = new AST.CompoundStatement(locFunc, s, body);
22282228
}
22292229
fd.fbody = body;
@@ -2373,14 +2373,13 @@ final class CParser(AST) : Parser!AST
23732373
}
23742374

23752375
AST.Type t;
2376-
Loc loc;
23772376
//printf("parseDeclarationSpecifiers()\n");
23782377

23792378
TKW tkw;
23802379
SCW scw = specifier.scw & SCW.xtypedef;
23812380
MOD mod;
2382-
Identifier id;
2383-
Identifier previd;
2381+
AST.ArgumentLabel id;
2382+
AST.ArgumentLabel previd;
23842383

23852384
Lwhile:
23862385
while (1)
@@ -2425,7 +2424,7 @@ final class CParser(AST) : Parser!AST
24252424

24262425
case TOK.identifier:
24272426
tkwx = TKW.xident;
2428-
id = token.ident;
2427+
id = AST.ArgumentLabel(token.ident, token.loc);
24292428
break;
24302429

24312430
case TOK.struct_:
@@ -2647,20 +2646,20 @@ final class CParser(AST) : Parser!AST
26472646

26482647
case TKW.xident:
26492648
{
2650-
const idx = previd.toString();
2649+
const idx = previd.name.toString();
26512650
if (idx.length > 2 && idx[0] == '_' && idx[1] == '_') // leading double underscore
26522651
importBuiltins = true; // probably one of those compiler extensions
26532652
t = null;
26542653

26552654
/* Punch through to what the typedef is, to support things like:
26562655
* typedef T* T;
26572656
*/
2658-
auto pt = lookupTypedef(previd);
2657+
auto pt = lookupTypedef(previd.name);
26592658
if (pt && *pt) // if previd is a known typedef
26602659
t = *pt;
26612660

26622661
if (!t)
2663-
t = new AST.TypeIdentifier(loc, previd);
2662+
t = new AST.TypeIdentifier(previd.loc, previd.name);
26642663
break;
26652664
}
26662665

@@ -2807,7 +2806,7 @@ final class CParser(AST) : Parser!AST
28072806
* declared struct, union or enum tags.
28082807
*/
28092808
private AST.Type cparseDeclarator(DTR declarator, AST.Type tbase,
2810-
out Identifier pident, ref Specifier specifier)
2809+
out AST.ArgumentLabel pident, ref Specifier specifier)
28112810
{
28122811
//printf("cparseDeclarator(%d, %s)\n", declarator, tbase.toChars());
28132812
AST.Types constTypes; // all the Types that will need `const` applied to them
@@ -2850,7 +2849,7 @@ final class CParser(AST) : Parser!AST
28502849
//printf("identifier %s\n", token.ident.toChars());
28512850
if (declarator == DTR.xabstract)
28522851
error("identifier not allowed in abstract-declarator");
2853-
pident = token.ident;
2852+
pident = AST.ArgumentLabel(token.ident, token.loc);
28542853
ts = t;
28552854
nextToken();
28562855
break;
@@ -3025,7 +3024,7 @@ final class CParser(AST) : Parser!AST
30253024
}
30263025
break;
30273026
}
3028-
if (declarator == DTR.xdirect && !pident)
3027+
if (declarator == DTR.xdirect && !pident.name)
30293028
error("expected identifier for declarator");
30303029
return ts;
30313030
}
@@ -3131,7 +3130,7 @@ final class CParser(AST) : Parser!AST
31313130
tspec = toConst(tspec);
31323131
specifier.mod = MOD.xnone; // 'used' it
31333132
}
3134-
Identifier id;
3133+
AST.ArgumentLabel id;
31353134
return cparseDeclarator(DTR.xabstract, tspec, id, specifier);
31363135
}
31373136

@@ -3209,6 +3208,7 @@ final class CParser(AST) : Parser!AST
32093208

32103209
Specifier specifier;
32113210
specifier.packalign.setDefault();
3211+
const typeLoc = token.loc;
32123212
auto tspec = cparseDeclarationSpecifiers(LVL.prototype, specifier);
32133213
if (!tspec)
32143214
{
@@ -3226,15 +3226,15 @@ final class CParser(AST) : Parser!AST
32263226
specifier.mod = MOD.xnone; // 'used' it
32273227
}
32283228

3229-
Identifier id;
3230-
const paramLoc = token.loc;
3229+
AST.ArgumentLabel id;
32313230
auto t = cparseDeclarator(DTR.xparameter, tspec, id, specifier);
32323231
if (token.value == TOK.__attribute__)
32333232
cparseGnuAttributes(specifier);
32343233
if (specifier.mod & MOD.xconst)
32353234
t = toConst(t);
3236-
auto param = new AST.Parameter(paramLoc, specifiersToSTC(LVL.parameter, specifier),
3237-
t, id, null, null);
3235+
auto param = new AST.Parameter(id.name ? id.loc : typeLoc,
3236+
specifiersToSTC(LVL.parameter, specifier),
3237+
t, id.name, null, null);
32383238
parameters.push(param);
32393239
if (token.value == TOK.rightParenthesis || token.value == TOK.endOfFile)
32403240
break;
@@ -4155,7 +4155,7 @@ final class CParser(AST) : Parser!AST
41554155

41564156
while (1)
41574157
{
4158-
Identifier id;
4158+
AST.ArgumentLabel id;
41594159
AST.Type dt;
41604160
if (token.value == TOK.colon)
41614161
{
@@ -4166,7 +4166,7 @@ final class CParser(AST) : Parser!AST
41664166
}
41674167

41684168
// C11 6.7.2.1-12 unnamed bit-field
4169-
id = Identifier.generateAnonymousId("BitField");
4169+
id.name = Identifier.generateAnonymousId("BitField");
41704170
dt = tspec;
41714171
}
41724172
else
@@ -4185,6 +4185,8 @@ final class CParser(AST) : Parser!AST
41854185
{
41864186
// C11 6.7.2.1-10 bit-field
41874187
nextToken();
4188+
if (id.name.isAnonymous)
4189+
id.loc = token.loc;
41884190
width = cparseConstantExp();
41894191
}
41904192

@@ -4202,18 +4204,18 @@ final class CParser(AST) : Parser!AST
42024204
{
42034205
if (specifier.alignasExp)
42044206
error(specifier.alignasExp.loc, "no alignment-specifier for bit field declaration"); // C11 6.7.5-2
4205-
auto s = new AST.BitFieldDeclaration(width.loc, dt, id, width);
4207+
auto s = new AST.BitFieldDeclaration(id.loc, dt, id.name, width);
42064208
members.push(s);
42074209
}
4208-
else if (id)
4210+
else if (id.name)
42094211
{
42104212
if (dt.ty == AST.Tvoid)
42114213
error("`void` has no value");
42124214

42134215
// declare the symbol
42144216
// Give member variables an implicit void initializer
42154217
auto initializer = new AST.VoidInitializer(token.loc);
4216-
AST.Dsymbol s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(LVL.member, specifier));
4218+
AST.Dsymbol s = new AST.VarDeclaration(id.loc, dt, id.name, initializer, specifiersToSTC(LVL.member, specifier));
42174219
s = applySpecifier(s, specifier);
42184220
members.push(s);
42194221
}

dmd/frontend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5993,6 +5993,7 @@ struct ASTCodegen final
59935993
typedef UserAttributeDeclaration* UserAttributeDeclaration;
59945994
typedef Ensure Ensure;
59955995
typedef ErrorExp* ErrorExp;
5996+
typedef ArgumentLabel ArgumentLabel;
59965997
typedef MODFlags MODFlags;
59975998
typedef Type* Type;
59985999
typedef Parameter* Parameter;

tests/dmd/compilable/jsonc.i

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ TEST_OUTPUT:
2525
"protection": "public"
2626
},
2727
{
28-
"char": 22,
28+
"char": 21,
2929
"deco": "VALUE_REMOVED_FOR_TEST",
3030
"kind": "alias",
3131
"line": 68,
@@ -50,7 +50,7 @@ TEST_OUTPUT:
5050
"protection": "public"
5151
},
5252
{
53-
"char": 38,
53+
"char": 36,
5454
"deco": "VALUE_REMOVED_FOR_TEST",
5555
"kind": "alias",
5656
"line": 70,

tests/dmd/fail_compilation/malformed_cmain.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/*
22
TEST_OUTPUT:
33
---
4-
fail_compilation/malformed_cmain.c(13): Error: function `malformed_cmain.main` parameters must match one of the following signatures
5-
fail_compilation/malformed_cmain.c(13): `main()`
6-
fail_compilation/malformed_cmain.c(13): `main(int argc, char** argv)`
7-
fail_compilation/malformed_cmain.c(13): `main(int argc, char** argv, char** environ)` [POSIX extension]
4+
fail_compilation/malformed_cmain.c(12): Error: function `malformed_cmain.main` parameters must match one of the following signatures
5+
fail_compilation/malformed_cmain.c(12): `main()`
6+
fail_compilation/malformed_cmain.c(12): `main(int argc, char** argv)`
7+
fail_compilation/malformed_cmain.c(12): `main(int argc, char** argv, char** environ)` [POSIX extension]
88
---
99
1010
*/

tests/dmd/fail_compilation/test22344.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* TEST_OUTPUT:
22
---
3-
fail_compilation/test22344.c(104): Error: function `test22344.func` redeclaration with different type
4-
fail_compilation/test22344.c(204): Error: function `test22344.test` redeclaration with different type
3+
fail_compilation/test22344.c(103): Error: function `test22344.func` redeclaration with different type
4+
fail_compilation/test22344.c(203): Error: function `test22344.test` redeclaration with different type
55
---
66
*/
77

tests/dmd/fail_compilation/testnothrow.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/* TEST_OUTPUT:
22
---
33
fail_compilation/testnothrow.c(105): Error: function `testnothrow.throwing` is not `nothrow`
4-
fail_compilation/testnothrow.c(104): Error: function `testnothrow.mul` may throw but is marked as `nothrow`
4+
fail_compilation/testnothrow.c(103): Error: function `testnothrow.mul` may throw but is marked as `nothrow`
55
fail_compilation/testnothrow.c(111): Error: function `testnothrow.throwing` is not `nothrow`
6-
fail_compilation/testnothrow.c(110): Error: function `testnothrow.add` may throw but is marked as `nothrow`
6+
fail_compilation/testnothrow.c(109): Error: function `testnothrow.add` may throw but is marked as `nothrow`
77
---
88
*/
99

0 commit comments

Comments
 (0)