================ idCompiler::ParseFunctionDef ================ */
| 2133 | ================ |
| 2134 | */ |
| 2135 | void idCompiler::ParseFunctionDef( idTypeDef *returnType, const char *name ) { |
| 2136 | idTypeDef *type; |
| 2137 | idVarDef *def; |
| 2138 | idVarDef *oldscope; |
| 2139 | int i; |
| 2140 | int numParms; |
| 2141 | const idTypeDef *parmType; |
| 2142 | function_t *func; |
| 2143 | statement_t *pos; |
| 2144 | |
| 2145 | if ( ( scope->Type() != ev_namespace ) && !scope->TypeDef()->Inherits( &type_object ) ) { |
| 2146 | Error( "Functions may not be defined within other functions" ); |
| 2147 | } |
| 2148 | |
| 2149 | type = ParseFunction( returnType, name ); |
| 2150 | def = gameLocal.program.GetDef( type, name, scope ); |
| 2151 | if ( !def ) { |
| 2152 | def = gameLocal.program.AllocDef( type, name, scope, true ); |
| 2153 | type->def = def; |
| 2154 | |
| 2155 | func = &gameLocal.program.AllocFunction( def ); |
| 2156 | if ( scope->TypeDef()->Inherits( &type_object ) ) { |
| 2157 | scope->TypeDef()->AddFunction( func ); |
| 2158 | } |
| 2159 | } else { |
| 2160 | func = def->value.functionPtr; |
| 2161 | assert( func ); |
| 2162 | if ( func->firstStatement ) { |
| 2163 | Error( "%s redeclared", def->GlobalName() ); |
| 2164 | } |
| 2165 | } |
| 2166 | |
| 2167 | // DG: make sure parmTotal gets calculated when parsing prototype (not just when parsing |
| 2168 | // implementation) so calling this function/method before the implementation has been parsed |
| 2169 | // works without getting Assertions in IdInterpreter::Execute() and ::LeaveFunction() |
| 2170 | // ("st->c->value.argSize == func->parmTotal", "localstackUsed == localstackBase", see #303 and #344) |
| 2171 | |
| 2172 | // calculate stack space used by parms |
| 2173 | numParms = type->NumParameters(); |
| 2174 | if ( !CheckToken( "{" ) ) { |
| 2175 | // it's just a prototype, so get the ; and move on |
| 2176 | ExpectToken( ";" ); |
| 2177 | // DG: BUT only after calculating the stack space for the arguments because this |
| 2178 | // function might be called before the implementation is parsed (see #303 and #344) |
| 2179 | // which otherwise causes Assertions in IdInterpreter::Execute() and ::LeaveFunction() |
| 2180 | // ("st->c->value.argSize == func->parmTotal", "localstackUsed == localstackBase") |
| 2181 | func->parmTotal = 0; |
| 2182 | for( i = 0; i < numParms; i++ ) { |
| 2183 | parmType = type->GetParmType( i ); |
| 2184 | int size = parmType->Inherits( &type_object ) ? type_object.Size() : parmType->Size(); |
| 2185 | func->parmTotal += size; |
| 2186 | // NOTE: Don't set func->parmSize[] yet, the workaround to keep compatibility |
| 2187 | // with old savegames checks for func->parmSize.Num() == 0 |
| 2188 | // (see EmitFunctionParms() for more explanation of that workaround) |
| 2189 | // Also not defining the parms yet, otherwise they're defined in a different order |
| 2190 | // than before, so their .num is different which breaks compat with old savegames |
| 2191 | } |
| 2192 | return; |
nothing calls this directly
no test coverage detected