Skip to content

Commit 8ef4b89

Browse files
committed
Attempt to fix #20410
1 parent 4e3b17e commit 8ef4b89

File tree

8 files changed

+152
-7
lines changed

8 files changed

+152
-7
lines changed

compiler/src/dmd/cparse.d

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5548,6 +5548,9 @@ final class CParser(AST) : Parser!AST
55485548
v.isCmacro = true; // mark it as coming from a C #define
55495549
if (auto td = s.isTemplateDeclaration())
55505550
td.isCmacro = true; // mark as coming from a C #define
5551+
if (auto ad = s.isAliasDeclaration())
5552+
ad.isCmacro = true; // ditto for vars and templates
5553+
55515554
/* If it's already defined, replace the earlier
55525555
* definition
55535556
*/
@@ -5702,6 +5705,47 @@ final class CParser(AST) : Parser!AST
57025705
}
57035706
break;
57045707

5708+
case TOK.identifier:
5709+
{
5710+
/* check for compiler builtins macros/ or specifier references.
5711+
* this is a workaround to avoid trying to resolve macros that
5712+
* reference other identifiers or functions
5713+
* so D users should avoid using custom macros beginning with __
5714+
* to reference identifers
5715+
*/
5716+
auto ident = token.ident;
5717+
Specifier sp;
5718+
sp.packalign = this.packalign;
5719+
auto tspec = cparseDeclarationSpecifiers(LVL.global, sp);
5720+
const idx = id.toString();
5721+
auto identx = ident.toString();
5722+
5723+
if (!tspec.isTypeIdentifier() || isCBuiltin(identx) || isCBuiltin(idx) ||
5724+
isCmacrosame(identx, idx) || (identx.length > 2 && identx[0] == '_' && identx[1] == '_')
5725+
|| (idx.length > 2 && idx[0] == '_' && idx[1] == '_'))
5726+
{
5727+
++p;
5728+
continue;
5729+
}
5730+
5731+
nextToken();
5732+
if (token.value != TOK.endOfFile)
5733+
{
5734+
++p;
5735+
continue;
5736+
}
5737+
5738+
/*
5739+
* #define identifier value where value can be an identifier.
5740+
* The identifier can be anything, so treat it as an AliasDeclaration.
5741+
* Mark it as coming from a C file to skip semantic resolution later.
5742+
*/
5743+
auto als = new AST.AliasDeclaration(scanloc, id, tspec);
5744+
addSym(als);
5745+
++p;
5746+
continue;
5747+
}
5748+
57055749
case TOK.leftParenthesis:
57065750
{
57075751
/* Look for:
@@ -5828,7 +5872,6 @@ final class CParser(AST) : Parser!AST
58285872
++p;
58295873
continue;
58305874
}
5831-
58325875
default:
58335876
break;
58345877
}
@@ -5862,3 +5905,39 @@ final class CParser(AST) : Parser!AST
58625905

58635906
//}
58645907
}
5908+
5909+
/*
5910+
* for few compiler intrinsics the compiler cannot resolve
5911+
* that we have no knowledge of in D,
5912+
* set them rawly and don't allow them for now
5913+
* long term, any user of a C header that is being bocked by an intrinsic,
5914+
* append to this table
5915+
*/
5916+
immutable string[] builtins = [
5917+
"_Pre_",
5918+
"_Maybevalid_impl_",
5919+
"_Pre_z_",
5920+
"_Notref_impl_",
5921+
"_Post_",
5922+
"X",
5923+
"_Use_decl_anno_impl_",
5924+
"vector_size",
5925+
"complex" // stay away from the C99 _complex keyword that share diffs on windows/POSIX
5926+
];
5927+
5928+
bool isCBuiltin(const(char)[] name)
5929+
{
5930+
foreach (b; builtins)
5931+
{
5932+
if (b == name)
5933+
return true;
5934+
}
5935+
return false;
5936+
}
5937+
5938+
bool isCmacrosame(const(char)[] idx, const(char)[] ident)
5939+
{
5940+
if (idx == ident)
5941+
return true;
5942+
return false;
5943+
}

compiler/src/dmd/declaration.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ extern (C++) final class AliasDeclaration : Declaration
341341

342342
Dsymbol overnext; // next in overload list
343343
Dsymbol _import; // !=null if unresolved internal alias for selective import
344+
bool isCmacro; // check whether it is coming from a C macro
344345

345346
extern (D) this(Loc loc, Identifier ident, Type type) @safe
346347
{

compiler/src/dmd/declaration.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ class AliasDeclaration final : public Declaration
196196
Dsymbol *aliassym;
197197
Dsymbol *overnext; // next in overload list
198198
Dsymbol *_import; // !=NULL if unresolved internal alias for selective import
199+
bool isCmacro;
199200

200201
static AliasDeclaration *create(Loc loc, Identifier *id, Type *type);
201202
AliasDeclaration *syntaxCopy(Dsymbol *) override;

compiler/src/dmd/dsymbolsem.d

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,7 @@ Dsymbol toAlias2(Dsymbol s)
11871187
{
11881188
if (auto ad = s.isAliasDeclaration())
11891189
{
1190-
if (ad.inuse)
1190+
if (ad.inuse && !ad.isCmacro) // c amcro can refer to itself and compile
11911191
{
11921192
.error(ad.loc, "%s `%s` recursive alias declaration", ad.kind, ad.toPrettyChars);
11931193
return ad;
@@ -1262,7 +1262,7 @@ private Dsymbol toAliasImpl(AliasDeclaration ad)
12621262
ad.inuse = 0;
12631263
}
12641264
}
1265-
if (ad.inuse)
1265+
if (ad.inuse && !ad.isCmacro) // C macros can refer to itself and comoile
12661266
{
12671267
.error(ad.loc, "%s `%s` recursive alias declaration", ad.kind, ad.toPrettyChars);
12681268
return err();
@@ -5825,8 +5825,9 @@ private extern(C++) class AddMemberVisitor : Visitor
58255825
}
58265826

58275827
// If using C tag/prototype/forward declaration rules
5828+
// remember, C allows rdececlarations of macros too
5829+
//(!sc.inCfie && dsym.isAliasDeclaration().isCmacro && s2.isAliasDeclaration().isCmacro)))
58285830
if (sc && sc.inCfile && !dsym.isImport())
5829-
// When merging master, replace with: if (sc && sc.inCfile && !dsym.isImport())
58305831
{
58315832
if (handleTagSymbols(*sc, dsym, s2, sds))
58325833
return;
@@ -6328,15 +6329,30 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
63286329
// Detect `alias sym = sym;` to prevent creating loops in overload overnext lists.
63296330
if (auto tident = ds.type.isTypeIdentifier())
63306331
{
6331-
if (sc.hasEdition(Edition.v2024) && tident.idents.length)
6332+
if ((sc.hasEdition(Edition.v2024) && tident.idents.length) || ds.isCmacro)
63326333
{
63336334
alias mt = tident;
63346335
Dsymbol pscopesym;
63356336
Dsymbol s = sc.search(ds.loc, mt.ident, pscopesym);
6337+
/* if the imported macro from C doesn't exist,
6338+
* probably a builtin one we don't define
6339+
* stop processing it. C macro refering identifiers
6340+
* can point to absolutely anything either defined or not
6341+
* #ifdefine hsgshsh hsshhshs is a valid C compile but emit on usage
6342+
* then we implement the ones we need
6343+
*/
6344+
if (!s && sc.inCfile && ds.isCmacro)
6345+
{
6346+
ds.aliassym = null;
6347+
ds.errors = false; // no error flag
6348+
ds.semanticRun = PASS.semanticdone; // mark semantic as complete
6349+
ds.inuse = 0; // clear recursion flag
6350+
return;
6351+
}
63366352
// detect `alias a = var1.member_var;` which confusingly resolves to
63376353
// `typeof(var1).member_var`, which can be valid inside the aggregate type
63386354
if (s && s.isVarDeclaration() &&
6339-
mt.ident != Id.This && mt.ident != Id._super)
6355+
mt.ident != Id.This && mt.ident != Id._super && (!ds.isCmacro && !sc.inCfile)) // don't let a C macro alias pass here
63406356
{
63416357
s = tident.toDsymbol(sc);
63426358
// don't error for `var1.static_symbol`
@@ -6350,7 +6366,7 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
63506366
}
63516367
}
63526368
// Selective imports are allowed to alias to the same name `import mod : sym=sym`.
6353-
if (!ds._import)
6369+
if (!ds._import && (!ds.isCmacro && !sc.inCfile)) // C identifier macros are not allowed here
63546370
{
63556371
if (tident.ident is ds.ident && !tident.idents.length)
63566372
{

compiler/src/dmd/frontend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6774,6 +6774,7 @@ class AliasDeclaration final : public Declaration
67746774
Dsymbol* aliassym;
67756775
Dsymbol* overnext;
67766776
Dsymbol* _import_;
6777+
bool isCmacro;
67776778
static AliasDeclaration* create(Loc loc, Identifier* id, Type* type);
67786779
AliasDeclaration* syntaxCopy(Dsymbol* s) override;
67796780
const char* kind() const override;

compiler/src/dmd/importc.d

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,23 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
490490
if (td.isCmacro) return s2;
491491
}
492492

493+
/* if (auto em = s.isEnumMember())
494+
{
495+
if (auto ad = s2.isAliasDeclaration())
496+
{
497+
if (ad.isCmacro)
498+
{
499+
return s;
500+
}
501+
}
502+
}*/
503+
504+
if (auto ad = s.isAliasDeclaration())
505+
{
506+
if (ad.isCmacro)
507+
return s2;
508+
}
509+
493510
auto vd = s.isVarDeclaration(); // new declaration
494511
auto vd2 = s2.isVarDeclaration(); // existing declaration
495512

compiler/test/runnable/fix20410.d

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
REQUIRED_ARGS: runnable/imports/imp20410.c
3+
*/
4+
//https://github.com/dlang/dmd/issues/20410
5+
import imp20410;
6+
7+
void main()
8+
{
9+
const _ = _RAX;
10+
11+
assert(num == 5);
12+
assert(func() == 9);
13+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// https://issues.dlang.org/show_bug.cgi?id=24419
2+
3+
typedef enum {
4+
#define R0 _RAX
5+
_RAX,
6+
} reg;
7+
8+
9+
int number = 5;
10+
#define num number;
11+
12+
13+
int function()
14+
{
15+
return 9;
16+
}
17+
#define func function

0 commit comments

Comments
 (0)