mirror of
https://github.com/dlang/dmd.git
synced 2025-04-27 05:30:13 +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)
|
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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************
|
/*************************
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
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