Skip to content

Commit 8c6b195

Browse files
committed
Handle nested macros with param expansion
1 parent ff53dec commit 8c6b195

File tree

5 files changed

+123
-93
lines changed

5 files changed

+123
-93
lines changed

src/cppconv/cppparallelparser.d

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,25 +1814,28 @@ void processMacroContent(ParserWrapper)(immutable(LocationContext)* locationCont
18141814
Tuple!(Tree, Location)[] mapParams(ParserWrapper)(Location start, Tree nameToken, MacroParam[string] paramMap,
18151815
Context!(ParserWrapper) context, Location funcMacroLocation, immutable(Formula)* condition)
18161816
{
1817+
auto startLoc = paramMap[nameToken.content].startLoc;
1818+
auto endLoc = paramMap[nameToken.content].endLoc;
1819+
bool goodParam = startLoc.context !is null && startLoc.context is endLoc.context;
1820+
1821+
assert(start.context.name.among("^", "##", "#"));
1822+
1823+
auto locationContextX1 = context.getLocationContext(immutable(LocationContext)(start.context,
1824+
start.context.name == "#" ? LocationN.init : nameToken.start.loc,
1825+
start.context.name == "#" ? LocationN.LocationDiff.init : nameToken.inputLength,
1826+
funcMacroLocation.context.prev.name ~ "." ~ nameToken.content,
1827+
goodParam ? startLoc.context.filename : ""));
1828+
18171829
Tuple!(Tree, Location)[] r;
18181830
foreach (i, t2; paramMap[nameToken.content].tokens)
18191831
{
18201832
LocationX commonLoc1 = t2.t.start;
18211833
LocationX commonLoc2 = funcMacroLocation;
18221834
findCommonLocationContext(commonLoc1, commonLoc2);
18231835

1824-
auto startLoc = paramMap[nameToken.content].startLoc;
1825-
auto endLoc = paramMap[nameToken.content].endLoc;
1826-
bool goodParam = startLoc.context !is null && startLoc.context is endLoc.context;
1827-
1828-
assert(start.context.name.among("^", "##"));
1829-
auto locationContextX1 = context.getLocationContext(immutable(LocationContext)(start.context,
1830-
nameToken.start.loc, nameToken.inputLength,
1831-
funcMacroLocation.context.prev.name ~ "." ~ nameToken.content,
1832-
goodParam ? startLoc.context.filename : ""));
1833-
auto locationContextX = context.getLocationContext(immutable(LocationContext)(locationContextX1, goodParam
1834-
? startLoc.loc : LocationN.init, goodParam
1835-
? (endLoc.loc - startLoc.loc) : LocationN.LocationDiff.init,
1836+
auto locationContextX = context.getLocationContext(immutable(LocationContext)(locationContextX1,
1837+
goodParam ? startLoc.loc : LocationN.init,
1838+
goodParam ? (endLoc.loc - startLoc.loc) : LocationN.LocationDiff.init,
18361839
"^", commonLoc1.context.filename));
18371840

18381841
context.locationContextInfoMap.getLocationContextInfo(locationContextX)
@@ -2079,33 +2082,30 @@ do
20792082

20802083
assert(start.context.name == "^");
20812084

2082-
string newText = "\"";
20832085
ParamToken[] paramTokens;
20842086
if (name in paramMap)
20852087
paramTokens = paramMap[name].tokens;
2086-
foreach (i, t2; paramTokens)
2087-
{
2088-
if (i && t2.t.start > paramTokens[i - 1].t.end)
2089-
{
2090-
newText ~= " ";
2091-
}
2092-
newText ~= t2.t.content.escapeD;
2093-
}
2094-
newText ~= "\"";
2095-
2096-
Tree newToken = Tree(newText, SymbolID.max, ProductionID.max, NodeType.token, []);
20972088

20982089
assert(token.start.context.filename == start.context.filename);
20992090
auto locationContextX0 = context.getLocationContext(immutable(LocationContext)(start.context,
2100-
token.start.loc, token.inputLength, "#", start.context.filename));
2091+
token.start.loc, token.inputLength, "#", ""));
2092+
2093+
Tuple!(Tree, Location)[] mappedTokens;
2094+
if (name in paramMap)
2095+
mappedTokens = mapParams(Location(LocationN.init, locationContextX0), token.childs[2], paramMap, context,
2096+
funcMacroLocation, condition);
21012097

21022098
Tree firstChild = Tree(token.childs[0].content, SymbolID.max,
21032099
ProductionID.max, NodeType.token, []);
21042100
firstChild.setStartEnd(start,
21052101
start + LocationN.LocationDiff.fromStr(token.childs[0].content));
21062102
Tree[] newChilds;
2107-
foreach (i, t2; paramTokens)
2108-
newChilds ~= t2.t;
2103+
foreach (i, t2; mappedTokens)
2104+
{
2105+
Tree token2 = Tree(t2[0].content, SymbolID.max, ProductionID.max, NodeType.token, []);
2106+
token2.setStartEnd(t2[1], t2[1] + t2[0].inputLength);
2107+
newChilds ~= token2;
2108+
}
21092109
Tree arr = createArrayTree(newChilds);
21102110
auto grammarInfo = getDummyGrammarInfo("ParamExpansion");
21112111
Tree sourceTokens = Tree("ParamExpansion", grammarInfo.startNonterminalID,
@@ -2116,25 +2116,24 @@ do
21162116
context.locationContextInfoMap.getLocationContextInfo(locationContextX0)
21172117
.condition = condition;
21182118

2119-
auto locationContextX1 = context.getLocationContext(immutable(LocationContext)(locationContextX0,
2120-
start.loc, token.inputLength, start.context.prev.name ~ "." ~ name, ""));
2121-
auto locationContextX = context.getLocationContext(
2122-
immutable(LocationContext)(locationContextX1, LocationN.init,
2123-
LocationN.LocationDiff.init, "^", funcMacroLocation.context.filename));
2124-
2125-
context.locationContextInfoMap.getLocationContextInfo(locationContextX)
2126-
.condition = condition;
2127-
2128-
LocationN start2, end2;
2129-
if (name in paramMap && paramMap[name].tokens.length)
2119+
LocationX lastEnd;
2120+
string newText = "\"";
2121+
foreach (i, t2; mappedTokens)
21302122
{
2131-
start2 = paramMap[name].tokens[0].t.start.loc;
2132-
end2 = paramMap[name].tokens[$ - 1].t.end.loc;
2123+
if (i && t2[1] > lastEnd)
2124+
{
2125+
newText ~= " ";
2126+
}
2127+
newText ~= t2[0].content.escapeD;
2128+
lastEnd = LocationX(t2[0].end.loc, t2[1].context);
21332129
}
2130+
newText ~= "\"";
2131+
2132+
Tree newToken = Tree(newText, SymbolID.max, ProductionID.max, NodeType.token, []);
21342133

2135-
newToken.setStartEnd(LocationX(start2, locationContextX),
2136-
LocationX(end2, locationContextX));
2137-
processDirectToken(LocationX(start2, locationContextX), newToken,
2134+
newToken.setStartEnd(Location(LocationN.init, locationContextX0),
2135+
Location(LocationN.init + Location.LocationDiff.fromStr(newText), locationContextX0));
2136+
processDirectToken(Location(LocationN.init, locationContextX0), newToken,
21382137
context, parallelParser, condition, macrosDone, false, parentParser);
21392138
}
21402139
else if (token.name == "ParamConcat")

src/cppconv/dwriter/macrodeclaration.d

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,20 @@ void collectMacroInstances(DWriterData data, Semantic mergedSemantic,
140140
data.macroInstanceByLocation[locationContextInfo.locationContext]
141141
= ConditionMap!MacroDeclarationInstance.init;
142142

143+
LocationContextInfo locationContextInfoWithTrees = locationContextInfo;
144+
if (paramName.length)
145+
{
146+
immutable(LocationContext)* locationContextMacro = macroFromParam(locationContext.prev);
147+
148+
for (LocationContextInfo loc3 = locationContextInfo; loc3.locationContext !is locationContextMacro; loc3 = loc3.parent)
149+
{
150+
if (loc3.locationContext.name == "#" || loc3.locationContext.name == "##")
151+
{
152+
locationContextInfoWithTrees = loc3;
153+
}
154+
}
155+
}
156+
143157
size_t numCombinations;
144158
foreach (combination; iterateCombinations())
145159
{
@@ -156,7 +170,7 @@ void collectMacroInstances(DWriterData data, Semantic mergedSemantic,
156170
mergedSemantic.logicSystem, firstCondition, null,
157171
mergedSemantic.mergedTreeDatas);
158172

159-
foreach (e; locationContextInfo.trees.entries)
173+
foreach (e; locationContextInfoWithTrees.trees.entries)
160174
{
161175
isInCorrectVersion(ppVersion, e.condition);
162176
}
@@ -166,7 +180,7 @@ void collectMacroInstances(DWriterData data, Semantic mergedSemantic,
166180
if (paramName.length)
167181
{
168182
if (locationContextInfo.mappedInParam
169-
&& locationContextInfo.trees.entries.length == 0)
183+
&& locationContextInfoWithTrees.trees.entries.length == 0)
170184
continue;
171185

172186
immutable(LocationContext)* locationContextMacro = macroFromParam(
@@ -189,15 +203,10 @@ void collectMacroInstances(DWriterData data, Semantic mergedSemantic,
189203
instance2.params[paramName].instances ~= instance;
190204
instance.macroDeclaration = instance2.params[paramName];
191205

192-
immutable(LocationContext)* loc3 = locationContext;
193-
while (loc3 !is locationContextMacro)
194-
{
195-
if (loc3.name == "#")
196-
instance.hasParamExpansion = true;
197-
if (loc3.name == "##")
198-
instance.hasMacroConcat = true;
199-
loc3 = loc3.prev;
200-
}
206+
if (locationContextInfoWithTrees.locationContext.name == "#")
207+
instance.hasParamExpansion = true;
208+
if (locationContextInfoWithTrees.locationContext.name == "##")
209+
instance.hasMacroConcat = true;
201210
}
202211
}
203212
}
@@ -239,7 +248,7 @@ void collectMacroInstances(DWriterData data, Semantic mergedSemantic,
239248
instance.locationContextInfo = locationContextInfo;
240249

241250
Tree[] macroTrees;
242-
foreach (ref e; locationContextInfo.trees.entries)
251+
foreach (ref e; locationContextInfoWithTrees.trees.entries)
243252
{
244253
if (mergedSemantic.logicSystem.and(e.condition, instanceEntry.condition).isFalse)
245254
continue;
@@ -544,16 +553,7 @@ void generateMacroCode(DWriterData data, Semantic mergedSemantic, MacroDeclarati
544553
MacroDeclaration macroDeclaration2;
545554
if (instance.macroDeclaration.type == DeclarationType.macroParam)
546555
{
547-
if (instance.macroDeclaration.type == DeclarationType.macroParam
548-
&& instance.hasParamExpansion)
549-
{
550-
LocationContextInfo info = instance.locationContextInfo;
551-
while (info.locationContext.name != "#")
552-
info = info.parent;
553-
554-
locRange = info.sourceTokens.childs[1].location;
555-
}
556-
else if (locationContext.parentLocation.context.filename.length)
556+
if (locationContext.parentLocation.context.filename.length)
557557
{
558558
locRange.setStartLength(LocationX(locationContext.parentLocation.start.loc,
559559
locationContext), locationContext.parentLocation.inputLength);
@@ -607,8 +607,6 @@ void generateMacroCode(DWriterData data, Semantic mergedSemantic, MacroDeclarati
607607
instance.macroDeclaration.definition.location.context.filename
608608
== locationContext.filename);
609609
}
610-
if (!locationContext.isParentOf(instance.macroTrees[0].start.context))
611-
locRange = LocationRangeX.init;
612610
if (locRange.context !is null)
613611
{
614612
foreach (i; 0 .. locRange.context.contextDepth - 1)
@@ -657,7 +655,28 @@ void generateMacroCode(DWriterData data, Semantic mergedSemantic, MacroDeclarati
657655
while (usedTrees.length == 1
658656
&& usedTrees[0].nonterminalID == nonterminalIDFor!"InitializerClause")
659657
usedTrees = usedTrees[0].childs[0 .. 1];
660-
instance.firstUsedTree = usedTrees[0];
658+
659+
Tree[] usedTreesOrig = usedTrees;
660+
bool isDirectParamExpansion;
661+
if (instance.macroDeclaration.type == DeclarationType.macroParam
662+
&& instance.hasParamExpansion)
663+
{
664+
LocationContextInfo info = instance.locationContextInfo;
665+
while (info.locationContext.name != "#")
666+
info = info.parent;
667+
usedTrees = [];
668+
foreach (t; info.sourceTokens.childs[1].childs)
669+
{
670+
if (isParentOf(locRange.context, t.location.context))
671+
usedTrees ~= t;
672+
}
673+
isDirectParamExpansion = info is instance.locationContextInfo.parent.parent;
674+
}
675+
676+
if (isDirectParamExpansion)
677+
instance.firstUsedTree = usedTreesOrig.length ? usedTreesOrig[0] : Tree.init;
678+
else
679+
instance.firstUsedTree = usedTrees.length ? usedTrees[0] : Tree.init;
661680

662681
TreeToCodeFlags treeToCodeFlags = TreeToCodeFlags.none;
663682
if (instance.macroDeclaration.type == DeclarationType.macro_)
@@ -669,18 +688,8 @@ void generateMacroCode(DWriterData data, Semantic mergedSemantic, MacroDeclarati
669688
treeToCodeFlags |= TreeToCodeFlags.skipCasts;
670689
size_t realCodeStart;
671690
size_t indexInParent;
672-
Tree parent = getRealParent(usedTrees[0], mergedSemantic, &indexInParent);
673-
if (instance.macroDeclaration.type == DeclarationType.macroParam
674-
&& instance.hasParamExpansion)
675-
{
676-
LocationContextInfo info = instance.locationContextInfo;
677-
while (info.locationContext.name != "#")
678-
info = info.parent;
679-
680-
foreach (t; info.sourceTokens.childs[1].childs)
681-
parseTreeToDCode(code, data, t, instanceCondition, null, treeToCodeFlags);
682-
}
683-
else if (parent.isValid && (parent.nonterminalID == nonterminalIDFor!"DeclSpecifierSeq"
691+
Tree parent = usedTrees.length ? getRealParent(usedTrees[0], mergedSemantic, &indexInParent) : Tree.init;
692+
if (parent.isValid && (parent.nonterminalID == nonterminalIDFor!"DeclSpecifierSeq"
684693
|| (parent.nonterminalID == nonterminalIDFor!"TypeId" && indexInParent == 0)))
685694
{
686695
ConditionMap!string codeType;
@@ -816,7 +825,7 @@ void generateMacroCode(DWriterData data, Semantic mergedSemantic, MacroDeclarati
816825
foreach (t; p.macroTrees)
817826
data.macroReplacement.remove(t);
818827

819-
foreach (usedTree; usedTrees)
828+
foreach (usedTree; isDirectParamExpansion ? usedTreesOrig : usedTrees)
820829
data.macroReplacement[usedTree] = instance;
821830

822831
sourceTokens.clear();

tests/single/test262b.d

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ extern(D) alias QT_STRINGIFY2 = function string(string x)
1212
return mixin(interpolateMixin(q{$(stringifyMacroParameter(x))}));
1313
};
1414
/+ #define QT_STRINGIFY(x) QT_STRINGIFY2(x) +/
15+
extern(D) alias QT_STRINGIFY = function string(string x)
16+
{
17+
return mixin(interpolateMixin(q{$(imported!q{test262b}.QT_STRINGIFY2(q{$(stringifyMacroParameter(x))}))}));
18+
};
1519

1620
/+ # define QT_STRINGIFY_SIGNAL(a) "2" #a +/
1721
extern(D) alias QT_STRINGIFY_SIGNAL = function string(string a)
@@ -22,13 +26,17 @@ extern(D) alias QT_STRINGIFY_SIGNAL = function string(string a)
2226
static if (!defined!"QT_NO_DEBUG")
2327
{
2428
/+ # define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__) +/
25-
enum QLOCATION = "\0" ~ __FILE__ ~ ":" ~ mixin(QT_STRINGIFY2(q{__LINE__}))/+ QT_STRINGIFY(__LINE__) +/;
29+
enum QLOCATION = "\0" ~ __FILE__ ~ ":" ~ mixin(QT_STRINGIFY(q{__LINE__}));
2630
/+ # define SLOT(a) qFlagLocation("1"#a QLOCATION) +/
2731
extern(D) alias SLOT = function string(string a)
2832
{
2933
return mixin(interpolateMixin(q{imported!q{test262b}.qFlagLocation("1"~ $(stringifyMacroParameter(a))~ imported!q{test262b}.QLOCATION)}));
3034
};
3135
/+ # define SIGNAL(a) qFlagLocation(QT_STRINGIFY_SIGNAL(a) QLOCATION) +/
36+
extern(D) alias SIGNAL = function string(string a)
37+
{
38+
return mixin(interpolateMixin(q{imported!q{test262b}.qFlagLocation($(imported!q{test262b}.QT_STRINGIFY_SIGNAL(q{$(stringifyMacroParameter(a))})) ~ imported!q{test262b}.QLOCATION)}));
39+
};
3240
}
3341
static if (defined!"QT_NO_DEBUG")
3442
{
@@ -38,6 +46,10 @@ extern(D) alias SLOT = function string(string a)
3846
return mixin(interpolateMixin(q{"1"~ $(stringifyMacroParameter(a))}));
3947
};
4048
/+ # define SIGNAL(a) QT_STRINGIFY_SIGNAL(a) +/
49+
extern(D) alias SIGNAL = function string(string a)
50+
{
51+
return mixin(interpolateMixin(q{$(imported!q{test262b}.QT_STRINGIFY_SIGNAL(q{$(stringifyMacroParameter(a))}))}));
52+
};
4153
}
4254

4355
extern(C++, class) struct QObject
@@ -49,10 +61,6 @@ public:
4961

5062
void f(QObject* a, QObject* b)
5163
{
52-
QObject.connect(a, mixin((!defined!"QT_NO_DEBUG") ? q{
53-
/+ SIGNAL(signalVoid()) +/qFlagLocation(mixin(QT_STRINGIFY_SIGNAL(q{signalVoid()}))~ QLOCATION)
54-
} : q{
55-
mixin(QT_STRINGIFY_SIGNAL(q{signalVoid()}))
56-
}), b, mixin(SLOT(q{onSignalVoid()})));
64+
QObject.connect(a, mixin(SIGNAL(q{signalVoid()})), b, mixin(SLOT(q{onSignalVoid()})));
5765
}
5866

tests/single/testdefines26.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ const char *line2 = __STRING2(__LINE__);
1313
const char *line3 = __STRING3(__LINE__);
1414
#define LOCATION __FILE__ ":" __STRING(__LINE__);
1515
const char *location1 = LOCATION;
16+
17+
const char *arr1 = __STRING(arr[i]);
18+
const char *arr2 = __STRING2(arr[i]);

tests/single/testdefines26.d

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,30 @@ extern(D) alias __STRING = function string(string x)
88
{
99
return mixin(interpolateMixin(q{$(stringifyMacroParameter(x))}));
1010
};
11-
/+ #define __STRING2(x) __STRING(x)
12-
#define __STRING3(x) __STRING(x x) +/
11+
/+ #define __STRING2(x) __STRING(x) +/
12+
extern(D) alias __STRING2 = function string(string x)
13+
{
14+
return mixin(interpolateMixin(q{$(imported!q{testdefines26}.__STRING(q{$(stringifyMacroParameter(x))}))}));
15+
};
16+
/+ #define __STRING3(x) __STRING(x x) +/
17+
extern(D) alias __STRING3 = function string(string x)
18+
{
19+
return mixin(interpolateMixin(q{$(imported!q{testdefines26}.__STRING(q{$(stringifyMacroParameter(x)) ~ $(stringifyMacroParameter(x))}))}));
20+
};
1321
__gshared const(char)* s1 = mixin(__STRING(q{test}));
14-
__gshared const(char)* s2 = mixin(__STRING(q{test2}))/+ __STRING2(test2) +/;
15-
__gshared const(char)* s3 = mixin(__STRING(q{test3 test3}))/+ __STRING3(test3) +/;
22+
__gshared const(char)* s2 = mixin(__STRING2(q{test2}));
23+
__gshared const(char)* s3 = mixin(__STRING3(q{test3}));
1624
/+ #define TEST2 test4 +/
1725
__gshared const(char)* s4 = mixin(__STRING(q{TEST4}));
1826
__gshared const(char)* s4b = mixin(__STRING(q{TEST4 x}));
1927

2028
__gshared const(char)* line1 = mixin(__STRING(q{__LINE__}));
21-
__gshared const(char)* line2 = mixin(__STRING(q{__LINE__}))/+ __STRING2(__LINE__) +/;
22-
__gshared const(char)* line3 = mixin(__STRING(q{__LINE__ __LINE__}))/+ __STRING3(__LINE__) +/;
29+
__gshared const(char)* line2 = mixin(__STRING2(q{__LINE__}));
30+
__gshared const(char)* line3 = mixin(__STRING3(q{__LINE__}));
2331
/+ #define LOCATION __FILE__ ":" __STRING(__LINE__); +/
2432
__gshared const(char)* location1 = /+ LOCATION +/__FILE__~ ":"~ mixin(__STRING(q{__LINE__}));
2533

2634

35+
__gshared const(char)* arr1 = mixin(__STRING(q{arr[i]}));
36+
__gshared const(char)* arr2 = mixin(__STRING2(q{arr[i]}));
37+

0 commit comments

Comments
 (0)