Skip to content

Commit

Permalink
Add casts to implicit pointer conversions
Browse files Browse the repository at this point in the history
  • Loading branch information
dkorpel committed Jul 17, 2023
1 parent d386051 commit 06679bc
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 14 deletions.
Binary file modified docs/ctod.wasm
Binary file not shown.
52 changes: 42 additions & 10 deletions source/ctod/cexpr.d
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,11 @@ bool ctodExpression(ref CtodCtx ctx, ref Node node) {
break;
case Sym.assignment_expression:
depthFirst();
if (auto l = node.childField(Field.left)) {

}
if (auto r = node.childField(Field.right)) {

}
auto l = node.childField(Field.left);
auto r = node.childField(Field.right);
assert(l);
assert(r);
convertPointerTypes(ctx, ctx.expType(*l), *r);
break;
case Sym.binary_expression:
depthFirst();
Expand Down Expand Up @@ -147,10 +146,10 @@ bool ctodExpression(ref CtodCtx ctx, ref Node node) {
}
}
}
ctx.setExpType(node, CType.pointer(CType.named("char")));
ctx.setExpType(node, CType.stringLiteral);
return true;
case Sym.string_literal:
ctx.setExpType(node, CType.pointer(CType.named("char")));
ctx.setExpType(node, CType.stringLiteral);
return true;
case Sym.cast_expression:
if (auto c = node.firstChildType(Sym.anon_LPAREN)) {
Expand Down Expand Up @@ -193,8 +192,14 @@ bool ctodExpression(ref CtodCtx ctx, ref Node node) {
}
}

if (translateSpecialFunction(node, *funcNode)) {
return true;
if (funcNode.typeEnum == Sym.identifier) {
const string funcName = funcNode.source;
if (funcName == "malloc" || funcName == "calloc" || funcName == "realloc") {
ctx.setExpType(node, CType.pointer(CType.named("void")));
}
if (translateSpecialFunction(node, *funcNode)) {
return true;
}
}
}
if (auto argsNode = node.childField(Field.arguments)) {
Expand Down Expand Up @@ -222,6 +227,33 @@ bool ctodExpression(ref CtodCtx ctx, ref Node node) {
return false;
}

/// C allows implicitly converting any T* -> U*, in D only T* -> `void*` gets that treatment
/// Try to fix this by adding explicit casts
void convertPointerTypes(ref CtodCtx ctx, CType lType, ref Node r) {
CType rType = ctx.expType(r);
if (lType.isPointer && rType.isPointer) {
if (lType.next[0] == rType.next[0]) {
return;
}
if (lType.next[0] == CType.named("void")) {
return; // D can implicitly convert to `void*`
}
if (rType == CType.stringLiteral) {
// This might be because of const mismatch,
// we don't want to simply cast away const with D string literals
return;
}
const castStr = "cast(" ~ lType.toString() ~ ") ";
// Always add parentheses to avoid operator precedence issues, except a few easy cases
if (r.typeEnum == Sym.call_expression || r.typeEnum == Sym.identifier) {
r.prepend(castStr);
} else {
r.prepend(castStr ~ "(");
r.append(")");
}
}
}

/// Translate special function calls
///
/// C's `offsetof()` macro becomes D's `.offsetof` property
Expand Down
9 changes: 9 additions & 0 deletions source/ctod/ctype.d
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ bool parseCtype(ref CtodCtx ctx, ref Node node, ref Decl decl, ref InlineType[]
ctx.inDeclType = decl.type;
translateNode(ctx, *valueNode);
ctx.inDeclType = CType.none;
convertPointerTypes(ctx, decl.type, *valueNode);
if (valueNode.typeEnum == Sym.initializer_list) {
string firstElem;
const len = initializerLength(*valueNode, firstElem);
Expand Down Expand Up @@ -596,6 +597,14 @@ struct CType {

pure nothrow:

/// Returns: type of string literal
static CType stringLiteral() {
auto cc = CType.named("char");
cc.isConst = true;
auto result = CType.pointer(cc);
return result;
}

bool opCast() const scope {return tag != Tag.none;}
bool isFunction() const {return tag == Tag.funcDecl;}
bool isStaticArray() const {return tag == Tag.staticArray;}
Expand Down
16 changes: 12 additions & 4 deletions source/ctod/test.d
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,24 @@ pragma(inline, true) private void foo(int* x, int function() y) {
// TODO: qualifiers in array parameter
// "void fquals(int x[const static 5]) {}"

// enhancement: add `cast(int*)` to return value of malloc
// Add `cast(int*)` to return value of malloc
test("
void main() {
int *x = malloc(4);
x = calloc(4);
x = calloc(5);
x = realloc(x, 6);
void *y = malloc(7);
void *z = x;
x = z;
}
", "
void main() {
int* x = malloc(4);
x = calloc(4);
int* x = cast(int*) malloc(4);
x = cast(int*) calloc(5);
x = cast(int*) realloc(x, 6);
void* y = malloc(7);
void* z = x;
x = cast(int*) z;
}
");

Expand Down

0 comments on commit 06679bc

Please sign in to comment.