Fixed CHECK failure when calling functions defined with repeated parameter names.

Clarified the terms "parameter" vs "argument" in FunctionParamList().
This commit is contained in:
acqn
2020-08-15 22:59:26 +08:00
committed by Oliver Schmidt
parent 531de44c95
commit ebae994dc9
2 changed files with 35 additions and 30 deletions

View File

@@ -330,32 +330,30 @@ static void WarnConstCompareResult (void)
static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
/* Parse a function parameter list, and pass the parameters to the called /* Parse a function parameter list, and pass the arguments to the called
** function. Depending on several criteria, this may be done by just pushing ** function. Depending on several criteria, this may be done by just pushing
** each parameter separately, or creating the parameter frame once, and then ** into each parameter separately, or creating the parameter frame once, and
** storing into this frame. ** then storing into this frame.
** The function returns the size of the parameters pushed. ** The function returns the size of the arguments pushed in bytes.
*/ */
{ {
ExprDesc Expr;
/* Initialize variables */ /* Initialize variables */
SymEntry* Param = 0; /* Keep gcc silent */ SymEntry* Param = 0; /* Keep gcc silent */
unsigned ParamSize = 0; /* Size of parameters pushed */ unsigned PushedSize = 0; /* Size of arguments pushed */
unsigned ParamCount = 0; /* Number of parameters pushed */ unsigned PushedCount = 0; /* Number of arguments pushed */
unsigned FrameSize = 0; /* Size of parameter frame */ unsigned FrameSize = 0; /* Size of parameter frame */
unsigned FrameParams = 0; /* Number of params in frame */ unsigned FrameParams = 0; /* Number of parameters in frame */
int FrameOffs = 0; /* Offset into parameter frame */ int FrameOffs = 0; /* Offset into parameter frame */
int Ellipsis = 0; /* Function is variadic */ int Ellipsis = 0; /* Function is variadic */
/* As an optimization, we may allocate the complete parameter frame at /* As an optimization, we may allocate the complete parameter frame at
** once instead of pushing each parameter as it comes. We may do that, ** once instead of pushing into each parameter as it comes. We may do that,
** if... ** if...
** **
** - optimizations that increase code size are enabled (allocating the ** - optimizations that increase code size are enabled (allocating the
** stack frame at once gives usually larger code). ** stack frame at once gives usually larger code).
** - we have more than one parameter to push (don't count the last param ** - we have more than one parameter to push into (don't count the last
** for __fastcall__ functions). ** parameter for __fastcall__ functions).
** **
** The FrameSize variable will contain a value > 0 if storing into a frame ** The FrameSize variable will contain a value > 0 if storing into a frame
** (instead of pushing) is enabled. ** (instead of pushing) is enabled.
@@ -367,7 +365,7 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
FrameParams = Func->ParamCount; FrameParams = Func->ParamCount;
FrameSize = Func->ParamSize; FrameSize = Func->ParamSize;
if (FrameParams > 0 && IsFastcall) { if (FrameParams > 0 && IsFastcall) {
/* Last parameter is not pushed */ /* Last parameter is not pushed into */
FrameSize -= CheckedSizeOf (Func->LastParam->Type); FrameSize -= CheckedSizeOf (Func->LastParam->Type);
--FrameParams; --FrameParams;
} }
@@ -384,25 +382,26 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
} }
} }
/* Parse the actual parameter list */ /* Parse the actual argument list */
while (CurTok.Tok != TOK_RPAREN) { while (CurTok.Tok != TOK_RPAREN) {
unsigned Flags; unsigned Flags;
ExprDesc Expr;
/* Count arguments */ /* Count arguments */
++ParamCount; ++PushedCount;
/* Fetch the pointer to the next argument, check for too many args */ /* Fetch the pointer to the next argument, check for too many args */
if (ParamCount <= Func->ParamCount) { if (PushedCount <= Func->ParamCount) {
/* Beware: If there are parameters with identical names, they /* Beware: If there are parameters with identical names, they
** cannot go into the same symbol table, which means that, in this ** cannot go into the same symbol table, which means that, in this
** case of errorneous input, the number of nodes in the symbol ** case of errorneous input, the number of nodes in the symbol
** table and ParamCount are NOT equal. We have to handle this case ** table and PushedCount are NOT equal. We have to handle this case
** below to avoid segmentation violations. Since we know that this ** below to avoid segmentation violations. Since we know that this
** problem can only occur if there is more than one parameter, ** problem can only occur if there is more than one parameter,
** we will just use the last one. ** we will just use the last one.
*/ */
if (ParamCount == 1) { if (PushedCount == 1) {
/* First argument */ /* First argument */
Param = Func->SymTab->SymHead; Param = Func->SymTab->SymHead;
} else if (Param->NextSym != 0) { } else if (Param->NextSym != 0) {
@@ -422,11 +421,11 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
Ellipsis = 1; Ellipsis = 1;
} }
/* Evaluate the parameter expression */ /* Evaluate the argument expression */
hie1 (&Expr); hie1 (&Expr);
/* If we don't have an argument spec., accept anything; otherwise, /* If we don't have a prototype, accept anything; otherwise, convert
** convert the actual argument to the type needed. ** the actual argument to the parameter type needed.
*/ */
Flags = CF_NONE; Flags = CF_NONE;
if (!Ellipsis) { if (!Ellipsis) {
@@ -483,7 +482,7 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
} }
/* Calculate total parameter size */ /* Calculate total parameter size */
ParamSize += ArgSize; PushedSize += ArgSize;
} }
/* Check for end of argument list */ /* Check for end of argument list */
@@ -499,20 +498,20 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
} }
} }
/* Check if we had enough parameters */ /* Check if we had enough arguments */
if (ParamCount < Func->ParamCount) { if (PushedCount < Func->ParamCount) {
Error ("Too few arguments in function call"); Error ("Too few arguments in function call");
} }
/* The function returns the size of all parameters pushed onto the stack. /* The function returns the size of all arguments pushed onto the stack.
** However, if there are parameters missing (which is an error, and was ** However, if there are parameters missed (which is an error, and was
** flagged by the compiler), AND a stack frame was preallocated above, ** flagged by the compiler), AND a stack frame was preallocated above,
** we would loose track of the stackpointer, and generate an internal error ** we would loose track of the stackpointer, and generate an internal error
** later. So we correct the value by the parameters that should have been ** later. So we correct the value by the parameters that should have been
** pushed, to avoid an internal compiler error. Since an error was ** pushed into, to avoid an internal compiler error. Since an error was
** generated before, no code will be output anyway. ** generated before, no code will be output anyway.
*/ */
return ParamSize + FrameSize; return PushedSize + FrameSize;
} }

View File

@@ -1032,6 +1032,7 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
/* Add a local symbol and return the symbol entry */ /* Add a local symbol and return the symbol entry */
{ {
SymTable* Tab = SymTab; SymTable* Tab = SymTab;
ident Ident;
/* Do we have an entry with this name already? */ /* Do we have an entry with this name already? */
SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
@@ -1065,10 +1066,15 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
} }
if (Entry == 0) { if (Entry == 0) {
if ((Flags & SC_PARAM) != 0) {
/* Use anonymous names */
Name = AnonName (Ident, "param");
} else {
/* Use the fail-safe table for fictitious symbols */ /* Use the fail-safe table for fictitious symbols */
Tab = FailSafeTab; Tab = FailSafeTab;
} }
} }
}
if (Entry == 0) { if (Entry == 0) {
/* Create a new entry */ /* Create a new entry */