fix Issue 22960 - importC: K&R-style functions assume variadic calling convention (#15107)

This commit is contained in:
Walter Bright 2023-04-19 00:51:31 -07:00 committed by GitHub
parent a4220358ec
commit 3981bdcd15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 28 additions and 9 deletions

View file

@ -3951,7 +3951,7 @@ struct ASTBase
extern (D) this(ParameterList pl, Type treturn, LINK linkage, StorageClass stc = 0) extern (D) this(ParameterList pl, Type treturn, LINK linkage, StorageClass stc = 0)
{ {
super(Tfunction, treturn); super(Tfunction, treturn);
assert(VarArg.none <= pl.varargs && pl.varargs <= VarArg.typesafe); assert(VarArg.none <= pl.varargs && pl.varargs <= VarArg.max);
this.parameterList = pl; this.parameterList = pl;
this.linkage = linkage; this.linkage = linkage;

View file

@ -327,6 +327,7 @@ enum VarArg : ubyte
variadic = 1, /// (T t, ...) can be C-style (core.stdc.stdarg) or D-style (core.vararg) variadic = 1, /// (T t, ...) can be C-style (core.stdc.stdarg) or D-style (core.vararg)
typesafe = 2, /// (T t ...) typesafe https://dlang.org/spec/function.html#typesafe_variadic_functions typesafe = 2, /// (T t ...) typesafe https://dlang.org/spec/function.html#typesafe_variadic_functions
/// or https://dlang.org/spec/function.html#typesafe_variadic_functions /// or https://dlang.org/spec/function.html#typesafe_variadic_functions
KRvariadic = 3, /// K+R C style variadics (no function prototype)
} }
/************************* /*************************

View file

@ -2081,8 +2081,7 @@ final class CParser(AST) : Parser!AST
auto pl = ft.parameterList; auto pl = ft.parameterList;
if (pl.varargs != AST.VarArg.none && pl.length) if (pl.varargs != AST.VarArg.none && pl.length)
error("function identifier-list cannot end with `...`"); error("function identifier-list cannot end with `...`");
ft.parameterList.varargs = AST.VarArg.variadic; // but C11 allows extra arguments ft.parameterList.varargs = AST.VarArg.KRvariadic; // but C11 allows extra arguments
importBuiltins = true; // will need __va_list_tag
auto plLength = pl.length; auto plLength = pl.length;
if (symbols.length != plLength) if (symbols.length != plLength)
error(token.loc, "%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length); error(token.loc, "%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length);
@ -3046,8 +3045,7 @@ final class CParser(AST) : Parser!AST
if (token.value == TOK.rightParenthesis) // func() if (token.value == TOK.rightParenthesis) // func()
{ {
nextToken(); nextToken();
importBuiltins = true; // will need __va_list_tag return AST.ParameterList(parameters, AST.VarArg.KRvariadic, varargsStc);
return AST.ParameterList(parameters, AST.VarArg.variadic, varargsStc);
} }
/* Create function prototype scope /* Create function prototype scope

View file

@ -2265,7 +2265,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
default: default:
break; break;
} }
if (tf.parameterList.varargs == VarArg.variadic) if (tf.parameterList.varargs == VarArg.variadic ||
tf.parameterList.varargs == VarArg.KRvariadic)
{ {
const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)"; const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
if (arg.type.ty == Tarray) if (arg.type.ty == Tarray)

View file

@ -2405,6 +2405,7 @@ enum class VarArg : uint8_t
none = 0u, none = 0u,
variadic = 1u, variadic = 1u,
typesafe = 2u, typesafe = 2u,
KRvariadic = 3u,
}; };
struct ParameterList final struct ParameterList final
@ -8873,7 +8874,9 @@ struct Id final
static Identifier* naked; static Identifier* naked;
static Identifier* thread; static Identifier* thread;
static Identifier* vector_size; static Identifier* vector_size;
static Identifier* noinline;
static Identifier* noreturn; static Identifier* noreturn;
static Identifier* _deprecated;
static Identifier* _align; static Identifier* _align;
static Identifier* aligned; static Identifier* aligned;
static Identifier* builtins; static Identifier* builtins;

View file

@ -1520,7 +1520,8 @@ tym_t totym(Type tx)
case LINK.windows: case LINK.windows:
if (target.is64bit) if (target.is64bit)
goto case LINK.c; goto case LINK.c;
t = (tf.parameterList.varargs == VarArg.variadic) ? TYnfunc : TYnsfunc; t = (tf.parameterList.varargs == VarArg.variadic ||
tf.parameterList.varargs == VarArg.KRvariadic) ? TYnfunc : TYnsfunc;
break; break;
case LINK.c: case LINK.c:

View file

@ -3229,6 +3229,7 @@ private void parametersToBuffer(ParameterList pl, OutBuffer* buf, HdrGenState* h
final switch (pl.varargs) final switch (pl.varargs)
{ {
case VarArg.none: case VarArg.none:
case VarArg.KRvariadic:
break; break;
case VarArg.variadic: case VarArg.variadic:

View file

@ -1722,7 +1722,8 @@ private bool canInline(FuncDeclaration fd, bool hasthis, bool hdrscan, bool stat
TypeFunction tf = fd.type.isTypeFunction(); TypeFunction tf = fd.type.isTypeFunction();
// no variadic parameter lists // no variadic parameter lists
if (tf.parameterList.varargs == VarArg.variadic) if (tf.parameterList.varargs == VarArg.variadic ||
tf.parameterList.varargs == VarArg.KRvariadic)
goto Lno; goto Lno;
/* No lazy parameters when inlining by statement, as the inliner tries to /* No lazy parameters when inlining by statement, as the inliner tries to

View file

@ -4267,7 +4267,7 @@ extern (C++) final class TypeFunction : TypeNext
super(Tfunction, treturn); super(Tfunction, treturn);
//if (!treturn) *(char*)0=0; //if (!treturn) *(char*)0=0;
// assert(treturn); // assert(treturn);
assert(VarArg.none <= pl.varargs && pl.varargs <= VarArg.typesafe); assert(VarArg.none <= pl.varargs && pl.varargs <= VarArg.max);
this.parameterList = pl; this.parameterList = pl;
this.linkage = linkage; this.linkage = linkage;

View file

@ -1316,6 +1316,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
* "argptr" extern(D) void dstyle(...), use `__argptr` and `__arguments` * "argptr" extern(D) void dstyle(...), use `__argptr` and `__arguments`
* "stdarg" extern(C) void cstyle(int, ...), use core.stdc.stdarg * "stdarg" extern(C) void cstyle(int, ...), use core.stdc.stdarg
* "typesafe" void typesafe(T[] ...) * "typesafe" void typesafe(T[] ...)
* "KR" old K+R style
*/ */
// get symbol linkage as a string // get symbol linkage as a string
if (dim != 1) if (dim != 1)
@ -1350,6 +1351,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
case VarArg.variadic: style = (link == LINK.d) case VarArg.variadic: style = (link == LINK.d)
? "argptr" ? "argptr"
: "stdarg"; break; : "stdarg"; break;
case VarArg.KRvariadic: style = "KR"; break;
case VarArg.typesafe: style = "typesafe"; break; case VarArg.typesafe: style = "typesafe"; break;
} }
auto se = new StringExp(e.loc, style); auto se = new StringExp(e.loc, style);

View file

@ -0,0 +1,11 @@
int abc() { return 1; }
int def(const char *p, ...) { return 2; }
int ghi(const char *p, int i) { return 3; }
int main()
{
abc("hello world %d\n", 1);
def("hello world %d\n", 2);
ghi("hello world %d\n", 3);
return 0;
}