diff --git a/source/dpp/translation/macro_.d b/source/dpp/translation/macro_.d index c4d9e8f6..de3f433a 100644 --- a/source/dpp/translation/macro_.d +++ b/source/dpp/translation/macro_.d @@ -366,8 +366,11 @@ private auto fixCasts(R)( if( // const type tokens.length >= 2 - && tokens[0] == Token(Token.Kind.Keyword, "const") - && isType(tokens[1..$]) + && ((tokens[0] == Token(Token.Kind.Keyword, "const") + && isType(tokens[1..$])) + || (tokens[$-1] == Token(Token.Kind.Keyword, "const") + && isType(tokens[0..$-1])) + ) ) return true; @@ -377,13 +380,22 @@ private auto fixCasts(R)( ) return true; - if ( // macro attribute (e.g. __force) + type + if( // e.g. (struct foo) var + tokens.length == 2 + && tokens[0] == Token(Token.Kind.Keyword, "struct") + && tokens[1].kind == Token.Kind.Identifier + // not checking for user defined type (foo might be given as parameter) + ) + return true; + + if( // macro attribute (e.g. __force) + type tokens.length >= 2 && tokens[0].kind == Token.Kind.Identifier && isType(tokens[1..$]) ) return true; + return false; } diff --git a/tests/it/c/compile/preprocessor.d b/tests/it/c/compile/preprocessor.d index 618003d2..2a736c2b 100644 --- a/tests/it/c/compile/preprocessor.d +++ b/tests/it/c/compile/preprocessor.d @@ -107,6 +107,34 @@ import it; } +@("user-defined struct cast in macro") +@safe unittest { + shouldCompile( + C( + ` + struct foo { int bar; }; + #define PTR(st, vr) ((struct st *) &vr) + #define PTR_CONST1(st, vr) ((const struct st *) &vr) + #define PTR_CONST2(st, vr) ((struct st const *) &vr) + #define PTR_CONST3(st, vr) ((struct st * const) &vr) + ` + ), + D( + q{ + foo f; + auto a = PTR(foo, f); + auto b = PTR_CONST1(foo, f); + + // DPP does not currently translate those "macro params" + // i.e. leaves "struct foo const *" unchanged + // auto c = PTR_CONST2(foo, f); + // auto d = PTR_CONST3(foo, f); + } + ) + ); +} + + version(Posix) // FIXME @("multiline") @safe unittest {