Skip to content

Commit 42be7d0

Browse files
committed
Fix semantic analysis for conflicts in braced init lists
1 parent e25dae4 commit 42be7d0

File tree

7 files changed

+292
-223
lines changed

7 files changed

+292
-223
lines changed

src/cppconv/conditiontree.d

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,12 @@ struct ConditionMap(T)
346346
}
347347
entries.length = i;
348348
}
349+
350+
void reset()
351+
{
352+
entries.length = 0;
353+
conditionAll = null;
354+
}
349355
}
350356

351357
void addCombine(alias F, T)(ref ConditionMap!T conditionMap, immutable(Formula)* condition, T data, LogicSystem logicSystem)

src/cppconv/cppsemantic.d

Lines changed: 8 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ class Semantic
104104
ComponentManager!TreeExtraInfo2 componentExtraInfo2;
105105
DeclarationExtra2*[Declaration] declarationExtra2Map;
106106

107+
static struct InitListState
108+
{
109+
bool inArray;
110+
Declaration[] fields;
111+
size_t currentField;
112+
}
113+
ConditionMap!InitListState currentInitListStates;
114+
107115
EntityID treeID(const Tree tree)
108116
{
109117
auto x = tree in treeToID;
@@ -485,75 +493,6 @@ void collectParameterExprs(Tree tree, ref IteratePPVersions ppVersion,
485493
}
486494
}
487495

488-
void collectParameterExprs2(Tree tree, immutable(Formula)* condition, Semantic semantic,
489-
ref ConditionMap!Tree parameterExprs, ref immutable(Formula)* hasNonterminal)
490-
{
491-
if (!tree.isValid)
492-
return;
493-
if (tree.nodeType == NodeType.array)
494-
{
495-
foreach (c; tree.childs)
496-
{
497-
collectParameterExprs2(c, condition, semantic, parameterExprs, hasNonterminal);
498-
}
499-
}
500-
else if (tree.nodeType == NodeType.merged)
501-
{
502-
auto mdata = &semantic.mergedTreeData(tree);
503-
504-
foreach (i; 0 .. tree.childs.length)
505-
{
506-
auto subTreeCondition = mdata.conditions[i];
507-
auto condition2 = semantic.logicSystem.and(semantic.logicSystem.or(subTreeCondition,
508-
semantic.logicSystem.and(mdata.mergedCondition,
509-
semantic.logicSystem.literal("#merged"))), condition);
510-
collectParameterExprs2(tree.childs[i], condition2, semantic, parameterExprs, hasNonterminal);
511-
}
512-
}
513-
else if (tree.nodeType == NodeType.nonterminal
514-
&& tree.nonterminalID == CONDITION_TREE_NONTERMINAL_ID)
515-
{
516-
auto ctree = tree.toConditionTree;
517-
assert(ctree !is null);
518-
519-
foreach (i; 0 .. ctree.childs.length)
520-
{
521-
auto subTreeCondition = ctree.conditions[i];
522-
523-
collectParameterExprs2(ctree.childs[i], semantic.logicSystem.and(subTreeCondition,
524-
condition), semantic, parameterExprs, hasNonterminal);
525-
}
526-
}
527-
else if (tree.nodeType == NodeType.token)
528-
{
529-
assert(tree.content == "," || tree.content == "..." || tree.content == "",
530-
text(locationStr(tree.start), " ", tree.content));
531-
if (tree.content == ",")
532-
{
533-
immutable(Formula)* doubleComma = semantic.logicSystem.and(condition,
534-
hasNonterminal.negated);
535-
if (!doubleComma.isFalse)
536-
{
537-
writeln("WARNING: unexpected or duplicate comma in arg list: ",
538-
locationStr(tree.start), " ", doubleComma.toString);
539-
parameterExprs.addNew(doubleComma, Tree.init, semantic.logicSystem);
540-
}
541-
hasNonterminal = semantic.logicSystem.and(hasNonterminal, condition.negated);
542-
}
543-
}
544-
else
545-
{
546-
if (!semantic.logicSystem.and(condition, hasNonterminal.negated).isFalse)
547-
parameterExprs.addNew(semantic.logicSystem.and(condition,
548-
hasNonterminal.negated), tree, semantic.logicSystem);
549-
immutable(Formula)* doubleNonterminal = semantic.logicSystem.and(condition, hasNonterminal);
550-
if (!doubleNonterminal.isFalse)
551-
writeln("WARNING: multiple nonterminals in arg list: ",
552-
locationStr(tree.start), " ", doubleNonterminal.toString);
553-
hasNonterminal = semantic.logicSystem.or(hasNonterminal, condition);
554-
}
555-
}
556-
557496
void analyzeDeclarator(Tree tree, ref IteratePPVersions ppVersion,
558497
ref SemanticRunInfo semantic, ref DeclaratorInfo info, QualType type)
559498
{
@@ -1215,59 +1154,6 @@ void collectRecordFieldsImpl(Tree tree, immutable(Formula)* condition,
12151154
}
12161155
}
12171156

1218-
void collectRecordFields2(Tree tree, immutable(Formula)* condition,
1219-
Semantic semantic, ref ConditionMap!Declaration declarations)
1220-
{
1221-
if (tree.nodeType == NodeType.token)
1222-
{
1223-
}
1224-
else if (tree.nodeType == NodeType.array)
1225-
{
1226-
foreach (i; 0 .. tree.childs.length)
1227-
{
1228-
collectRecordFields2(tree.childs[i], condition, semantic, declarations);
1229-
}
1230-
}
1231-
else if (tree.nodeType == NodeType.nonterminal
1232-
&& tree.nonterminalID == CONDITION_TREE_NONTERMINAL_ID)
1233-
{
1234-
auto ctree = tree.toConditionTree;
1235-
assert(ctree !is null);
1236-
1237-
foreach (i; 0 .. ctree.childs.length)
1238-
{
1239-
auto subTreeCondition = ctree.conditions[i];
1240-
1241-
collectRecordFields2(ctree.childs[i], semantic.logicSystem.and(subTreeCondition,
1242-
condition), semantic, declarations);
1243-
}
1244-
}
1245-
else if (tree.nonterminalID == ParserWrapper.nonterminalIDFor!"ClassSpecifier")
1246-
{
1247-
collectRecordFields2(tree.childs[1], condition, semantic, declarations);
1248-
}
1249-
else if (tree.nonterminalID == ParserWrapper.nonterminalIDFor!"ClassBody")
1250-
{
1251-
collectRecordFields2(tree.childs[1], condition, semantic, declarations);
1252-
}
1253-
else if (tree.name.startsWith("SimpleDeclaration") || tree.name.startsWith("MemberDeclaration")
1254-
|| tree.nonterminalID.nonterminalIDAmong!("FunctionDefinitionMember",
1255-
"FunctionDefinitionGlobal", "MemberDeclaration" /*, "ParameterDeclaration", "ParameterDeclarationAbstract"*/ ))
1256-
{
1257-
foreach (d; semantic.extraInfo(tree).declarations)
1258-
{
1259-
if ((d.flags & DeclarationFlags.static_) != 0)
1260-
continue;
1261-
if ((d.flags & DeclarationFlags.function_) != 0)
1262-
continue;
1263-
if (d.type == DeclarationType.type)
1264-
continue;
1265-
1266-
declarations.addNew(condition, d, semantic.logicSystem);
1267-
}
1268-
}
1269-
}
1270-
12711157
void analyzeSwitch(Semantic semantic, Tree tree, immutable(Formula)* condition,
12721158
ref immutable(Formula)* afterStatement)
12731159
{

src/cppconv/cppsemantic1.d

Lines changed: 72 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,30 +1548,16 @@ void runSemantic(ref SemanticRunInfo semantic, ref Tree tree, Tree parent,
15481548
}, (MatchNonterminals!("BracedInitList")) {
15491549
updateType(extraInfoHere.type, semantic.extraInfo(realParent).type);
15501550

1551+
assert(semantic.currentInitListStates.entries.length == 0);
1552+
15511553
foreach (combination; iterateCombinations())
15521554
{
15531555
IteratePPVersions ppVersion = IteratePPVersions(combination, semantic.logicSystem,
15541556
condition, semantic.instanceCondition, semantic.mergedTreeDatas);
15551557
auto expectedType2 = chooseType(semantic.extraInfo(realParent).type, ppVersion, true);
15561558
if (expectedType2.type !is null && expectedType2.kind == TypeKind.array)
15571559
{
1558-
auto t = cast(ArrayType) expectedType2.type;
1559-
1560-
ConditionMap!Tree parameterExprs;
1561-
immutable(Formula)* hasNonterminal = semantic.logicSystem.false_;
1562-
collectParameterExprs2(tree.childs[1], ppVersion.condition,
1563-
semantic, parameterExprs, hasNonterminal);
1564-
1565-
foreach (param; parameterExprs.entries)
1566-
{
1567-
if (!param.data.isValid)
1568-
continue;
1569-
assert(param.data.nonterminalID.nonterminalIDAmong!("InitializerClause",
1570-
"InitializerClauseDesignator"));
1571-
auto extraInfoChild = &semantic.extraInfo(param.data);
1572-
extraInfoChild.type = combineTypes(extraInfoChild.type, t.next, null,
1573-
semantic.logicSystem.and(ppVersion.condition, param.condition), semantic);
1574-
}
1560+
semantic.currentInitListStates.addReplace(ppVersion.condition, Semantic.InitListState(true), semantic.logicSystem);
15751561
}
15761562
else if (expectedType2.type !is null && expectedType2.kind == TypeKind.record)
15771563
{
@@ -1587,108 +1573,93 @@ void runSemantic(ref SemanticRunInfo semantic, ref Tree tree, Tree parent,
15871573
if (!isInCorrectVersion(ppVersion, e.condition))
15881574
continue;
15891575

1590-
ConditionMap!Declaration recordFields;
1591-
collectRecordFields2(e.data.tree, ppVersion.condition, semantic, recordFields);
1576+
Declaration[] recordFields;
1577+
collectRecordFields(e.data.tree, ppVersion.condition, semantic, ppVersion, recordFields);
1578+
semantic.currentInitListStates.addReplace(ppVersion.condition, Semantic.InitListState(false, recordFields), semantic.logicSystem);
1579+
}
1580+
}
1581+
}
15921582

1593-
ConditionMap!Tree parameterExprs;
1594-
immutable(Formula)* hasNonterminal = semantic.logicSystem.false_;
1595-
collectParameterExprs2(tree.childs[1], ppVersion.condition,
1596-
semantic, parameterExprs, hasNonterminal);
1583+
foreach (ref c; tree.childs)
1584+
{
1585+
runSemantic(semantic, c, tree, condition);
1586+
}
15971587

1598-
ConditionMap!size_t[2] currentRecordStart;
1599-
bool currentRecordStartI;
1600-
currentRecordStart[0].addNew(ppVersion.condition, 0, semantic.logicSystem);
1601-
currentRecordStart[1].addNew(ppVersion.condition, 0, semantic.logicSystem);
1588+
semantic.currentInitListStates.reset();
1589+
}, (MatchNonterminals!("InitializerClause", "InitializerClauseDesignator")) {
1590+
ConditionMap!(Semantic.InitListState) savedInitListStates;
1591+
savedInitListStates.swap(semantic.currentInitListStates);
16021592

1603-
foreach (param; parameterExprs.entries)
1604-
{
1605-
if (!param.data.isValid)
1606-
continue;
1607-
auto extraInfoChild = &semantic.extraInfo(param.data);
1608-
if (param.data.nonterminalID == nonterminalIDFor!"InitializerClause")
1609-
{
1610-
currentRecordStart[!currentRecordStartI].entries.length
1611-
= currentRecordStart[currentRecordStartI].entries.length;
1612-
currentRecordStart[!currentRecordStartI].entries.toSlice[]
1613-
= currentRecordStart[currentRecordStartI].entries.toSlice[];
1593+
if (realParent.nonterminalID == nonterminalIDFor!"BracedInitList")
1594+
{
1595+
ConditionMap!(Semantic.InitListState) newInitListStates;
1596+
foreach (e; savedInitListStates.entries)
1597+
{
1598+
auto condition2 = semantic.logicSystem.and(e.condition, condition.negated);
1599+
if (!condition2.isFalse)
1600+
newInitListStates.addReplace(condition2, e.data, semantic.logicSystem);
1601+
}
1602+
foreach (combination; iterateCombinations())
1603+
{
1604+
IteratePPVersions ppVersion = IteratePPVersions(combination, semantic.logicSystem,
1605+
condition, semantic.instanceCondition, semantic.mergedTreeDatas);
1606+
auto expectedType2 = chooseType(semantic.extraInfo(realParent).type, ppVersion, true);
1607+
auto initListState = savedInitListStates.choose(ppVersion);
16141608

1615-
foreach (combination2; iterateCombinations())
1616-
{
1617-
IteratePPVersions ppVersion2 = IteratePPVersions(combination2, semantic.logicSystem,
1618-
semantic.logicSystem.and(ppVersion.condition, param.condition),
1619-
semantic.instanceCondition, semantic.mergedTreeDatas);
1620-
size_t start = currentRecordStart[currentRecordStartI].choose(
1621-
ppVersion2);
1622-
while (start < recordFields.entries.length
1623-
&& !isInCorrectVersion(ppVersion2,
1624-
recordFields.entries[start].condition))
1625-
start++;
1626-
1627-
if (start < recordFields.entries.length)
1628-
{
1629-
extraInfoChild.type = combineTypes(extraInfoChild.type,
1630-
recordFields.entries[start].data.type2,
1631-
null, ppVersion2.condition, semantic);
1609+
if (initListState.inArray)
1610+
{
1611+
auto t = cast(ArrayType) expectedType2.type;
16321612

1633-
start++;
1634-
}
1635-
currentRecordStart[!currentRecordStartI].addReplace(ppVersion2.condition,
1636-
start, semantic.logicSystem, true);
1637-
}
1638-
currentRecordStartI = !currentRecordStartI;
1613+
extraInfoHere.type = combineTypes(extraInfoHere.type, t.next, null,
1614+
semantic.logicSystem.and(ppVersion.condition, condition), semantic);
1615+
}
1616+
else if (tree.nonterminalID == nonterminalIDFor!"InitializerClauseDesignator")
1617+
{
1618+
assert(tree.childs[0].nodeType == NodeType.array);
1619+
if (tree.childs[0].childs.length == 1)
1620+
{
1621+
auto designator = tree.childs[0].childs[0];
1622+
Declaration d;
1623+
foreach (f; initListState.fields)
1624+
{
1625+
if (f.name == designator.childs[1].content)
1626+
d = f;
16391627
}
1640-
else if (param.data.nonterminalID == nonterminalIDFor!"InitializerClauseDesignator")
1628+
if (d !is null)
16411629
{
1642-
assert(param.data.childs[0].nodeType == NodeType.array);
1643-
if (param.data.childs[0].childs.length == 1)
1644-
{
1645-
auto designator = param.data.childs[0].childs[0];
1646-
Declaration d;
1647-
foreach (f; recordFields.entries)
1648-
{
1649-
if (f.data.name == designator.childs[1].content)
1650-
d = f.data;
1651-
}
1652-
if (d !is null)
1653-
{
1654-
extraInfoChild.referenced.add(semantic.logicSystem.and(ppVersion.condition,
1655-
param.condition), d.declarationSet, semantic.logicSystem);
1656-
extraInfoChild.type = combineTypes(extraInfoChild.type, d.type2, null,
1657-
semantic.logicSystem.and(ppVersion.condition,
1658-
param.condition), semantic);
1659-
}
1660-
}
1661-
else
1662-
writeln("TODO: InitializerClauseDesignator ",
1663-
locationStr(tree.location));
1630+
extraInfoHere.referenced.add(semantic.logicSystem.and(ppVersion.condition,
1631+
condition), d.declarationSet, semantic.logicSystem);
1632+
extraInfoHere.type = combineTypes(extraInfoHere.type, d.type2, null,
1633+
semantic.logicSystem.and(ppVersion.condition,
1634+
condition), semantic);
16641635
}
1665-
else
1666-
writeln("TODO: ", param.data.name, " ", locationStr(tree.location));
16671636
}
1637+
else
1638+
writeln("TODO: InitializerClauseDesignator ",
1639+
locationStr(tree.location));
1640+
}
1641+
else if (initListState.currentField < initListState.fields.length)
1642+
{
1643+
extraInfoHere.type = combineTypes(extraInfoHere.type,
1644+
initListState.fields[initListState.currentField].type2,
1645+
null, semantic.logicSystem.and(ppVersion.condition, condition), semantic);
1646+
initListState.currentField++;
16681647
}
1648+
newInitListStates.addReplace(ppVersion.condition, initListState, semantic.logicSystem);
16691649
}
1650+
savedInitListStates.swap(newInitListStates);
16701651
}
1671-
1672-
foreach (ref c; tree.childs)
1673-
{
1674-
runSemantic(semantic, c, tree, condition);
1675-
}
1676-
}, (MatchNonterminals!("InitializerClause")) {
1677-
if (realParent.name != "BracedInitList")
1652+
else
16781653
updateType(extraInfoHere.type, semantic.extraInfo(realParent).type);
1654+
16791655
foreach (ref c; tree.childs)
16801656
{
16811657
runSemantic(semantic, c, tree, condition);
16821658
}
1683-
if (realParent.name != "BracedInitList")
1659+
if (realParent.nonterminalID != nonterminalIDFor!"BracedInitList")
16841660
updateType(extraInfoHere.type, semantic.extraInfo(tree.childs[0]).type);
1685-
}, (MatchNonterminals!("InitializerClauseDesignator")) {
1686-
if (realParent.name != "BracedInitList")
1687-
updateType(extraInfoHere.type, semantic.extraInfo(realParent).type);
1688-
foreach (ref c; tree.childs)
1689-
{
1690-
runSemantic(semantic, c, tree, condition);
1691-
}
1661+
1662+
semantic.currentInitListStates.swap(savedInitListStates);
16921663
}, (MatchProductions!((p, nonterminalName, symbolNames) => nonterminalName == "PostfixExpression"
16931664
&& symbolNames.length == 4 && symbolNames[1] == q{"("} && !p.symbols[0].isToken)) {
16941665
runSemantic(semantic, tree.childs[2], tree, condition);

0 commit comments

Comments
 (0)