Skip to content

Commit 7551b85

Browse files
committed
Handle grammar ambiguity in if condition
1 parent 99b121c commit 7551b85

File tree

7 files changed

+124
-2
lines changed

7 files changed

+124
-2
lines changed

src/cppconv/cppsemantic.d

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,6 +2212,13 @@ void handleConflictExpression(Tree tree, ref immutable(Formula)* goodConditionSt
22122212
handleConflictExpression(tree.childs[1], goodConditionStrict,
22132213
goodCondition, semantic, ConflictExpressionFlags.none);
22142214
}
2215+
else if (tree.nonterminalID == nonterminalIDFor!"Condition")
2216+
{
2217+
handleConflictExpression(tree.childs[0], goodConditionStrict,
2218+
goodCondition, semantic, ConflictExpressionFlags.inType);
2219+
handleConflictExpression(tree.childs[1], goodConditionStrict,
2220+
goodCondition, semantic, ConflictExpressionFlags.none);
2221+
}
22152222
else if (tree.nonterminalID == nonterminalIDFor!"DeclSpecifierSeq")
22162223
{
22172224
handleConflictExpression(tree.childs[0], goodConditionStrict,

src/cppconv/cppsemantic1.d

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ void runSemantic(ref SemanticRunInfo semantic, ref Tree tree, Tree parent,
213213
|| tree.name.endsWith("StaticAssertDeclarationX")
214214
|| tree.name.endsWith("Statement")
215215
|| tree.nonterminalID == nonterminalIDFor!"TemplateArgumentList"
216-
|| tree.nonterminalID == nonterminalIDFor!"InitializerList";
216+
|| tree.nonterminalID == nonterminalIDFor!"InitializerList"
217+
|| tree.nonterminalID == nonterminalIDFor!"Condition";
217218
}())
218219
{
219220
immutable(Formula)* goodConditionStrict = condition;

src/cppconv/dwriter/treecode.d

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,14 +963,34 @@ void parseTreeToDCode(T)(ref CodeWriter code, DWriterData data, T tree, immutabl
963963
{
964964
auto codeWrapper = ConditionalCodeWrapper(condition, data);
965965

966-
codeWrapper.checkTree(tree.childs, false);
966+
bool shouldDescent(Tree tree)
967+
{
968+
if (tree.nonterminalID == nonterminalIDFor!"IfStatementHead"
969+
&& tree.childs[2].nodeType == NodeType.merged)
970+
{
971+
auto mdata = &semantic.mergedTreeData(tree.childs[2]);
972+
foreach (i, c; tree.childs[2].childs)
973+
if (c.nonterminalID == nonterminalIDFor!"Condition"
974+
&& !mdata.conditions[i].isFalse)
975+
return true;
976+
}
977+
return false;
978+
}
979+
980+
codeWrapper.checkTree(tree.childs, false, &shouldDescent);
967981

968982
if (codeWrapper.alwaysUseMixin)
969983
{
970984
codeWrapper.begin(code, condition);
971985

972986
void onTree(Tree t, immutable(Formula)* condition2)
973987
{
988+
if (shouldDescent(t))
989+
{
990+
foreach (c; t.childs)
991+
codeWrapper.writeTree(code, &onTree, c, condition2);
992+
return;
993+
}
974994
parseTreeToDCode(code, data, t, condition2, currentScope);
975995
writeComments(code, data, data.sourceTokenManager.collectTokens(t.location.end));
976996
writeComments(code, data,

tests/single/test389.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class C
2+
{
3+
};
4+
C *createC();
5+
void f()
6+
{
7+
if (C *x = createC())
8+
{}
9+
}

tests/single/test389.d

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module test389;
2+
3+
import config;
4+
import cppconvhelpers;
5+
6+
extern(C++, class) struct C
7+
{
8+
}
9+
C* createC();
10+
void f()
11+
{
12+
if (C* x = createC())
13+
{}
14+
}
15+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifdef DEF
2+
class a
3+
{
4+
};
5+
a *c;
6+
#else
7+
struct S
8+
{
9+
S &operator *(S)
10+
{
11+
return *this;
12+
}
13+
explicit operator bool() const
14+
{
15+
return true;
16+
}
17+
};
18+
S a, b, c;
19+
#endif
20+
void f()
21+
{
22+
if (a *b = c)
23+
{}
24+
}

tests/single/testconflict_md_s_1.d

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
module testconflict_md_s_1;
2+
3+
import config;
4+
import cppconvhelpers;
5+
6+
static if (defined!"DEF")
7+
{
8+
extern(C++, class) struct a
9+
{
10+
}
11+
__gshared a* c;
12+
}
13+
static if (!defined!"DEF")
14+
{
15+
struct S
16+
{
17+
ref S opBinary(string op)(S) if (op == "*")
18+
{
19+
return this;
20+
}
21+
/+ explicit +/ auto opCast(T : bool)() const
22+
{
23+
return true;
24+
}
25+
}
26+
__gshared S a;
27+
__gshared S b;
28+
__gshared S c;
29+
}
30+
void f()
31+
{
32+
mixin(q{if (
33+
}
34+
~ (!defined!"DEF" ? q{
35+
(){return a *.b = c;
36+
}()
37+
}:"")
38+
~ (defined!"DEF" ? q{
39+
a* b__1=c
40+
}:"")
41+
~ q{
42+
)
43+
{}
44+
}
45+
);}
46+

0 commit comments

Comments
 (0)