Skip to content

Commit 0726ec7

Browse files
committed
Avoid extra stringified macro parameters
1 parent ee03b09 commit 0726ec7

7 files changed

Lines changed: 238 additions & 26 deletions

File tree

src/cppconv/dwriter/dwriter.d

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3274,8 +3274,9 @@ void writeAllDCode(string outputPath, bool outputIsDir, DCodeOptions options, Se
32743274
data.macroReplacement = null;
32753275
foreach (ref mergedFile; mergedFiles)
32763276
{
3277+
bool[immutable(LocationContext)*] applyMacroInstancesDone;
32773278
applyMacroInstances(data, mergedSemantic,
3278-
mergedFile.locationContextInfoMap.getLocationContextInfo(null));
3279+
mergedFile.locationContextInfoMap.getLocationContextInfo(null), applyMacroInstancesDone);
32793280
}
32803281

32813282
File outfile;

src/cppconv/dwriter/macrodeclaration.d

Lines changed: 124 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,80 @@ void collectMacroInstances(DWriterData data, Semantic mergedSemantic,
431431
}
432432
}
433433

434-
void generateMacroCode(DWriterData data, Semantic mergedSemantic, LocationContextInfo locationContextInfo, MacroDeclarationInstance instance)
434+
void selectMacroParamNames(DWriterData data, Semantic mergedSemantic, MacroDeclarationInstance instance)
435435
{
436+
// Select names for macro parameters
437+
if (instance.macroDeclaration.type == DeclarationType.macro_ && instance.params.length)
438+
{
439+
foreach (n, p; instance.params)
440+
{
441+
string nonStringifiedName;
442+
bool canReplaceStringifiedParam = true;
443+
foreach (instance2; p.instances)
444+
{
445+
auto key = text(instance2.macroTranslation, " ", instance2.instanceCode);
446+
if (instance2.hasMacroConcat)
447+
canReplaceStringifiedParam = false;
448+
if (instance2.hasParamExpansion)
449+
continue;
450+
if (key in instance2.macroDeclaration.nameByCode)
451+
{
452+
instance2.usedName = instance2.macroDeclaration.nameByCode[key];
453+
}
454+
else
455+
{
456+
string name2;
457+
if (instance2.macroDeclaration.nameByCode.length)
458+
name2 = text(instance2.macroDeclaration.name, "__",
459+
instance2.macroDeclaration.nameByCode.length + 2);
460+
else
461+
name2 = replaceKeywords(instance2.macroDeclaration.name);
462+
instance2.macroDeclaration.nameByCode[key] = name2;
463+
instance2.usedName = name2;
464+
}
465+
nonStringifiedName = instance2.usedName;
466+
}
467+
if (p.nameByCode.length != 1)
468+
canReplaceStringifiedParam = false;
469+
foreach (instance2; p.instances)
470+
{
471+
auto key = text(instance2.macroTranslation, " ", instance2.instanceCode);
472+
if (!instance2.hasParamExpansion)
473+
continue;
474+
if (canReplaceStringifiedParam)
475+
{
476+
/* Reuse other parameter name for stringified parameter
477+
This is a special case for macros like this:
478+
#define F(code) if (code) printf(#code);
479+
The parameter could be different when translated to D,
480+
but stringified macro parameters are often for
481+
debugging and we can use the translated string, so
482+
no extra version of the parameter is necessary. */
483+
instance2.usedName = nonStringifiedName;
484+
}
485+
else if (key in instance2.macroDeclaration.nameByCode)
486+
{
487+
instance2.usedName = instance2.macroDeclaration.nameByCode[key];
488+
}
489+
else
490+
{
491+
string name2;
492+
if (instance2.macroDeclaration.nameByCode.length)
493+
name2 = text(instance2.macroDeclaration.name, "__",
494+
instance2.macroDeclaration.nameByCode.length + 2);
495+
else
496+
name2 = replaceKeywords(instance2.macroDeclaration.name);
497+
instance2.macroDeclaration.nameByCode[key] = name2;
498+
instance2.usedName = name2;
499+
}
500+
}
501+
}
502+
}
503+
}
504+
505+
void generateMacroCode(DWriterData data, Semantic mergedSemantic, MacroDeclarationInstance instance)
506+
{
507+
LocationContextInfo locationContextInfo = instance.locationContextInfo;
436508
auto locationContext = locationContextInfo.locationContext;
437509

438510
static Appender!(SourceToken[]) sourceTokens;
@@ -716,25 +788,6 @@ void generateMacroCode(DWriterData data, Semantic mergedSemantic, LocationContex
716788
instance.usedName = name2;
717789
}
718790
}
719-
else if (instance.macroDeclaration.type == DeclarationType.macroParam)
720-
{
721-
auto key = text(instance.macroTranslation, " ", instance.instanceCode);
722-
if (key in instance.macroDeclaration.nameByCode)
723-
{
724-
instance.usedName = instance.macroDeclaration.nameByCode[key];
725-
}
726-
else
727-
{
728-
string name2;
729-
if (instance.macroDeclaration.nameByCode.length)
730-
name2 = text(instance.macroDeclaration.name, "__",
731-
instance.macroDeclaration.nameByCode.length + 2);
732-
else
733-
name2 = replaceKeywords(instance.macroDeclaration.name);
734-
instance.macroDeclaration.nameByCode[key] = name2;
735-
instance.usedName = name2;
736-
}
737-
}
738791

739792
foreach (ps; instance.params)
740793
foreach (p; ps.instances)
@@ -748,12 +801,60 @@ void generateMacroCode(DWriterData data, Semantic mergedSemantic, LocationContex
748801
}
749802

750803
void applyMacroInstances(DWriterData data, Semantic mergedSemantic,
751-
LocationContextInfo locationContextInfo)
804+
LocationContextInfo locationContextInfo, ref bool[immutable(LocationContext)*] done)
752805
{
806+
if (locationContextInfo.locationContext in done)
807+
{
808+
assert(done[locationContextInfo.locationContext], text(locationStr(locationContextInfo.locationContext)));
809+
return;
810+
}
811+
812+
done[locationContextInfo.locationContext] = false;
813+
scope(exit)
814+
done[locationContextInfo.locationContext] = true;
815+
816+
// Handle macro parameters earlier
817+
if (locationContextInfo.locationContext in data.macroInstanceByLocation)
818+
{
819+
foreach (instanceEntry; data
820+
.macroInstanceByLocation[locationContextInfo.locationContext].entries)
821+
{
822+
MacroDeclarationInstance instance = instanceEntry.data;
823+
824+
if (instance.macroTranslation == MacroTranslation.none)
825+
continue;
826+
827+
if (instance.macroDeclaration.type == DeclarationType.macro_ && instance.params.length)
828+
{
829+
foreach (n, p; instance.params)
830+
{
831+
foreach (instance2; p.instances)
832+
{
833+
applyMacroInstances(data, mergedSemantic, instance2.locationContextInfo, done);
834+
}
835+
}
836+
}
837+
}
838+
839+
foreach (instanceEntry; data
840+
.macroInstanceByLocation[locationContextInfo.locationContext].entries)
841+
{
842+
MacroDeclarationInstance instance = instanceEntry.data;
843+
844+
if (instance.macroTranslation == MacroTranslation.none)
845+
continue;
846+
847+
if (instance.macroDeclaration.type == DeclarationType.macro_ && instance.params.length)
848+
{
849+
selectMacroParamNames(data, mergedSemantic, instance);
850+
}
851+
}
852+
}
853+
753854
for (LocationContextInfo child = locationContextInfo.firstChild; child !is null;
754855
child = child.next)
755856
{
756-
applyMacroInstances(data, mergedSemantic, child);
857+
applyMacroInstances(data, mergedSemantic, child, done);
757858
}
758859

759860
if (locationContextInfo.locationContext !in data.macroInstanceByLocation)
@@ -767,6 +868,6 @@ void applyMacroInstances(DWriterData data, Semantic mergedSemantic,
767868
if (instance.macroTranslation == MacroTranslation.none)
768869
continue;
769870

770-
generateMacroCode(data, mergedSemantic, locationContextInfo, instance);
871+
generateMacroCode(data, mergedSemantic, instance);
771872
}
772873
}

src/cppconv/dwriter/treecode.d

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,10 @@ void parseTreeToDCode(T)(ref CodeWriter code, DWriterData data, T tree, immutabl
313313
{
314314
if (y.usedName == paramName.usedName)
315315
{
316-
x = y;
316+
if (x is null || !y.hasParamExpansion)
317+
x = y;
317318
}
318-
if (y.instanceCode != paramInstances[0].instanceCode)
319+
else
319320
allCodesSame = false;
320321
}
321322
if (!allCodesSame)

tests/single/test170.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
struct S
2+
{
3+
const char *name;
4+
void (*f)(void);
5+
};
6+
7+
void f1(void);
8+
void f2(void);
9+
10+
#define M(x) {#x, x}
11+
12+
const struct S funcs[] = {M(f1), M(f2)};

tests/single/test170.d

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module test170;
2+
3+
import config;
4+
import cppconvhelpers;
5+
6+
struct S
7+
{
8+
const(char)* name;
9+
void function() f;
10+
}
11+
12+
void f1();
13+
void f2();
14+
15+
/+ #define M(x) {#x, x} +/
16+
extern(D) alias M = function string(string x)
17+
{
18+
return mixin(interpolateMixin(q{const(imported!q{test170}.S)($(stringifyMacroParameter(x)), $(x))}));
19+
};
20+
21+
__gshared /+ const(S)[0] +/ auto funcs = mixin(buildStaticArray!(q{const(S)}, q{ mixin(M(q{&f1})), mixin(M(q{&f2}))}));
22+

tests/single/test387.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
template<class T>
2+
bool f()
3+
{
4+
return true;
5+
}
6+
7+
struct S
8+
{
9+
template<class T>
10+
bool f()
11+
{
12+
return true;
13+
}
14+
};
15+
16+
void printf(const char *fmt, ...);
17+
18+
#define CHECK(statement) \
19+
do { \
20+
if (!static_cast<bool>(statement)) \
21+
printf("Failed: %s\n", #statement); \
22+
} while (false)
23+
24+
int main()
25+
{
26+
CHECK(true);
27+
CHECK(f<S>());
28+
S x;
29+
CHECK(x.f<S>());
30+
return 0;
31+
}

tests/single/test387.d

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
module test387;
2+
3+
import config;
4+
import cppconvhelpers;
5+
6+
bool f(T)()
7+
{
8+
return true;
9+
}
10+
11+
struct S
12+
{
13+
/+ template<class T> +/
14+
bool f(T)()
15+
{
16+
return true;
17+
}
18+
}
19+
20+
void printf(const(char)* fmt, ...);
21+
22+
/+ #define CHECK(statement) \
23+
do { \
24+
if (!static_cast<bool>(statement)) \
25+
printf("Failed: %s\n", #statement); \
26+
} while (false) +/
27+
extern(D) alias CHECK = function string(string statement)
28+
{
29+
return
30+
mixin(interpolateMixin(q{ do {
31+
if (!static_cast!(bool)($(statement)))
32+
imported!q{test387}.printf("Failed: %s\n", $(stringifyMacroParameter(statement)));
33+
} while (false);}));
34+
};
35+
36+
int main()
37+
{
38+
mixin(CHECK(q{true}));
39+
mixin(CHECK(q{f!(S)()}));
40+
S x;
41+
mixin(CHECK(q{x.f!(S)()}));
42+
return 0;
43+
}
44+

0 commit comments

Comments
 (0)