mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00
fix Issue 22960 - importC: K&R-style functions assume variadic calling convention (#15107)
This commit is contained in:
parent
a4220358ec
commit
3981bdcd15
11 changed files with 28 additions and 9 deletions
|
@ -3951,7 +3951,7 @@ struct ASTBase
|
|||
extern (D) this(ParameterList pl, Type treturn, LINK linkage, StorageClass stc = 0)
|
||||
{
|
||||
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.linkage = linkage;
|
||||
|
||||
|
|
|
@ -327,6 +327,7 @@ enum VarArg : ubyte
|
|||
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
|
||||
/// or https://dlang.org/spec/function.html#typesafe_variadic_functions
|
||||
KRvariadic = 3, /// K+R C style variadics (no function prototype)
|
||||
}
|
||||
|
||||
/*************************
|
||||
|
|
|
@ -2081,8 +2081,7 @@ final class CParser(AST) : Parser!AST
|
|||
auto pl = ft.parameterList;
|
||||
if (pl.varargs != AST.VarArg.none && pl.length)
|
||||
error("function identifier-list cannot end with `...`");
|
||||
ft.parameterList.varargs = AST.VarArg.variadic; // but C11 allows extra arguments
|
||||
importBuiltins = true; // will need __va_list_tag
|
||||
ft.parameterList.varargs = AST.VarArg.KRvariadic; // but C11 allows extra arguments
|
||||
auto plLength = pl.length;
|
||||
if (symbols.length != plLength)
|
||||
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()
|
||||
{
|
||||
nextToken();
|
||||
importBuiltins = true; // will need __va_list_tag
|
||||
return AST.ParameterList(parameters, AST.VarArg.variadic, varargsStc);
|
||||
return AST.ParameterList(parameters, AST.VarArg.KRvariadic, varargsStc);
|
||||
}
|
||||
|
||||
/* Create function prototype scope
|
||||
|
|
|
@ -2265,7 +2265,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
default:
|
||||
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++)";
|
||||
if (arg.type.ty == Tarray)
|
||||
|
|
|
@ -2405,6 +2405,7 @@ enum class VarArg : uint8_t
|
|||
none = 0u,
|
||||
variadic = 1u,
|
||||
typesafe = 2u,
|
||||
KRvariadic = 3u,
|
||||
};
|
||||
|
||||
struct ParameterList final
|
||||
|
@ -8873,7 +8874,9 @@ struct Id final
|
|||
static Identifier* naked;
|
||||
static Identifier* thread;
|
||||
static Identifier* vector_size;
|
||||
static Identifier* noinline;
|
||||
static Identifier* noreturn;
|
||||
static Identifier* _deprecated;
|
||||
static Identifier* _align;
|
||||
static Identifier* aligned;
|
||||
static Identifier* builtins;
|
||||
|
|
|
@ -1520,7 +1520,8 @@ tym_t totym(Type tx)
|
|||
case LINK.windows:
|
||||
if (target.is64bit)
|
||||
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;
|
||||
|
||||
case LINK.c:
|
||||
|
|
|
@ -3229,6 +3229,7 @@ private void parametersToBuffer(ParameterList pl, OutBuffer* buf, HdrGenState* h
|
|||
final switch (pl.varargs)
|
||||
{
|
||||
case VarArg.none:
|
||||
case VarArg.KRvariadic:
|
||||
break;
|
||||
|
||||
case VarArg.variadic:
|
||||
|
|
|
@ -1722,7 +1722,8 @@ private bool canInline(FuncDeclaration fd, bool hasthis, bool hdrscan, bool stat
|
|||
TypeFunction tf = fd.type.isTypeFunction();
|
||||
|
||||
// no variadic parameter lists
|
||||
if (tf.parameterList.varargs == VarArg.variadic)
|
||||
if (tf.parameterList.varargs == VarArg.variadic ||
|
||||
tf.parameterList.varargs == VarArg.KRvariadic)
|
||||
goto Lno;
|
||||
|
||||
/* No lazy parameters when inlining by statement, as the inliner tries to
|
||||
|
|
|
@ -4267,7 +4267,7 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
super(Tfunction, treturn);
|
||||
//if (!treturn) *(char*)0=0;
|
||||
// assert(treturn);
|
||||
assert(VarArg.none <= pl.varargs && pl.varargs <= VarArg.typesafe);
|
||||
assert(VarArg.none <= pl.varargs && pl.varargs <= VarArg.max);
|
||||
this.parameterList = pl;
|
||||
this.linkage = linkage;
|
||||
|
||||
|
|
|
@ -1316,6 +1316,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
* "argptr" extern(D) void dstyle(...), use `__argptr` and `__arguments`
|
||||
* "stdarg" extern(C) void cstyle(int, ...), use core.stdc.stdarg
|
||||
* "typesafe" void typesafe(T[] ...)
|
||||
* "KR" old K+R style
|
||||
*/
|
||||
// get symbol linkage as a string
|
||||
if (dim != 1)
|
||||
|
@ -1350,6 +1351,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
case VarArg.variadic: style = (link == LINK.d)
|
||||
? "argptr"
|
||||
: "stdarg"; break;
|
||||
case VarArg.KRvariadic: style = "KR"; break;
|
||||
case VarArg.typesafe: style = "typesafe"; break;
|
||||
}
|
||||
auto se = new StringExp(e.loc, style);
|
||||
|
|
11
compiler/test/compilable/cvariadic.i
Normal file
11
compiler/test/compilable/cvariadic.i
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue