Skip to content

Commit

Permalink
fix Issue 22102 - importC: Error: function is used as a type
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuclaw committed Jul 7, 2021
1 parent 512716e commit 0c931e5
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 2 deletions.
53 changes: 53 additions & 0 deletions src/dmd/cparse.d
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,19 @@ final class CParser(AST) : Parser!AST
case TOK.rightShiftAssign:
goto Lexp;

case TOK.leftParenthesis:
{
/* Ambiguous cases arise for declarations in the style:
* typedef-name ( identifier ) ;
* As type-name won't be resolved until semantic, prefer
* to first assume it is a call expression, and rewrite later.
*/
auto tk = &token;
if (isFunctionCall(tk))
goto Lexp;
goto default;
}

default:
{
/* If tokens look like a declaration, assume it is one
Expand Down Expand Up @@ -3208,6 +3221,46 @@ final class CParser(AST) : Parser!AST
return true;
}

/********************************
* See if match for:
* postfix-expression ( argument-expression-list(opt) )
* Params:
* pt = starting token, updated to one past end of initializer if true
* Returns:
* true if function call
*/
private bool isFunctionCall(ref Token* pt)
{
//printf("isFunctionCall()\n");
auto t = pt;

if (!isPrimaryExpression(t))
return false;
if (t.value != TOK.leftParenthesis)
return false;
t = peek(t);
while (1)
{
if (!isAssignmentExpression(t))
return false;
if (t.value == TOK.comma)
{
t = peek(t);
continue;
}
if (t.value == TOK.rightParenthesis)
{
t = peek(t);
break;
}
return false;
}
if (t.value != TOK.semicolon)
return false;
pt = t;
return true;
}

/********************************
* See if match for assignment-expression.
* Params:
Expand Down
34 changes: 34 additions & 0 deletions src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -4463,6 +4463,40 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Rewrite (*fp)(arguments) to fp(arguments)
exp.e1 = (cast(PtrExp)exp.e1).e1;
}
else if (exp.e1.op == TOK.type && (sc && sc.flags & SCOPE.Cfile))
{
/* Ambiguous cases arise from CParser where there is not enough
* information to determine if we have a function call or declaration.
* type-name ( identifier ) ;
* identifier ( identifier ) ;
* If exp.e1 is a type-name, then this is a declaration. C11 does not
* have type construction syntax, so don't convert this to a cast().
*/
if (exp.arguments && exp.arguments.dim == 1)
{
Expression arg = (*exp.arguments)[0];
if (auto ie = (*exp.arguments)[0].isIdentifierExp())
{
TypeExp te = cast(TypeExp)exp.e1;
auto initializer = new VoidInitializer(ie.loc);
Dsymbol s = new VarDeclaration(ie.loc, te.type, ie.ident, initializer);
auto decls = new Dsymbols(1);
(*decls)[0] = s;
s = new LinkDeclaration(s.loc, LINK.c, decls);
result = new DeclarationExp(exp.loc, s);
result = result.expressionSemantic(sc);
}
else
{
arg.error("identifier or `(` expected");
result = ErrorExp.get();
}
return;
}
exp.error("identifier or `(` expected before `)`");
result = ErrorExp.get();
return;
}
}

Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
Expand Down
16 changes: 14 additions & 2 deletions test/compilable/testcstuff2.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ void test22063()

void test22066()
{
int var = 0;
(var)++;
int var = 0;
(var)++;
}

/***************************************************/
Expand Down Expand Up @@ -320,6 +320,18 @@ void test22088()
c = ld;
}

/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=22102

void fun22102(int var);
typedef int int22102;

void test22102()
{
int22102(var);
fun22102(var);
}

/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=22103

Expand Down
16 changes: 16 additions & 0 deletions test/fail_compilation/failcstuff1.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ fail_compilation/failcstuff1.c(460): Error: variable length arrays are not suppo
fail_compilation/failcstuff1.c(460): Error: variable length array used outside of function prototype
fail_compilation/failcstuff1.c(461): Error: array type has incomplete element type `int[]`
fail_compilation/failcstuff1.c(462): Error: `=`, `;` or `,` expected
fail_compilation/failcstuff1.c(502): Error: identifier or `(` expected
fail_compilation/failcstuff1.c(502): Error: found `;` when expecting `)`
fail_compilation/failcstuff1.c(503): Error: `=`, `;` or `,` expected
fail_compilation/failcstuff1.c(504): Error: identifier or `(` expected
fail_compilation/failcstuff1.c(504): Error: found `;` when expecting `)`
fail_compilation/failcstuff1.c(505): Error: `=`, `;` or `,` expected
---
*/

Expand Down Expand Up @@ -132,3 +138,13 @@ void test22103e()
int array4[][];
int array4[4] const;
}

// https://issues.dlang.org/show_bug.cgi?id=22102
#line 500
void test22102()
{
int(0);
int var1;
int();
int var2;
}
13 changes: 13 additions & 0 deletions test/fail_compilation/failcstuff2.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ fail_compilation/failcstuff2.c(204): Error: variable `var` is used as a type
fail_compilation/failcstuff2.c(203): variable `var` is declared here
fail_compilation/failcstuff2.c(205): Error: variable `var` is used as a type
fail_compilation/failcstuff2.c(203): variable `var` is declared here
fail_compilation/failcstuff2.c(254): Error: identifier or `(` expected before `)`
fail_compilation/failcstuff2.c(255): Error: identifier or `(` expected
---
*/

Expand Down Expand Up @@ -97,3 +99,14 @@ void test21992(int var)
var = (var) ~ 1234;
var = (var) ! 1234;
}

/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=22102
#line 250
typedef int int22102;

void test22102()
{
int22102();
int22102(0);
}

0 comments on commit 0c931e5

Please sign in to comment.