Skip to content

foreach statement over POD value types #92

Description

@suprstefan

Hi, I'm having an issue with foreach over POD value types. If I manually make a for-loop with opForX it works but when using a foreach it crashes because the this pointer is garbage (tested on windows x64 VS 2026). Here's a very rough unittest for it where the first for-loop works and the second foreach-loop crashes on both 2.38.0 and latest main:

	{
		asIScriptEngine* engine = asCreateScriptEngine();
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";

		RegisterStdString(engine);

		engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(Print_Generic), asCALL_GENERIC);

		struct PodIterator
		{
			PodIterator(asUINT* values, asUINT length) : _values(values), _length(length) {}

			asUINT opForBegin() {
				return 0;
			}
			bool opForEnd(asUINT it) {
				return it >= _length;
			}
			asUINT opForNext(asUINT it) {
				return it + 1;
			}
			asUINT opForValue(asUINT it) {
				return _values[it];
			}

			asUINT _length;
			asUINT* _values;
		};

		engine->RegisterObjectType("PodIterator", sizeof(PodIterator), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<PodIterator>());
		engine->RegisterObjectMethod("PodIterator", "uint opForBegin()", asMETHODPR(PodIterator, opForBegin, (), asUINT), asCALL_THISCALL);
		engine->RegisterObjectMethod("PodIterator", "bool opForEnd(uint it)", asMETHODPR(PodIterator, opForEnd, (asUINT), bool), asCALL_THISCALL);
		engine->RegisterObjectMethod("PodIterator", "uint opForNext(uint it)", asMETHODPR(PodIterator, opForNext, (asUINT), asUINT), asCALL_THISCALL);
		engine->RegisterObjectMethod("PodIterator", "uint opForValue(uint it)", asMETHODPR(PodIterator, opForValue, (asUINT), asUINT), asCALL_THISCALL);

		g_printBuffer = "";

		asIScriptModule* mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("foreachpod",
			"void main(PodIterator obj) {"
			"	for(auto it = obj.opForBegin(); !obj.opForEnd(it); it = obj.opForNext(it)) {\n"
			"		print(format(\"{}\", obj.opForValue(it)));\n"
			"	}\n"
			"	foreach(auto a : obj) {\n"
			"		print(format(\"{}\", a));\n"
			"	}\n"
			"}\n");
		r = mod->Build();
		if (r < 0)
			TEST_FAILED;

		asUINT values[] = { 0,1,2,3,4 };
		PodIterator itr(values, sizeof(values) / sizeof(values[0]));

		asIScriptFunction* func = mod->GetFunctionByName("main");
		asIScriptContext* ctx = engine->RequestContext();
		ctx->Prepare(func);
		ctx->SetArgObject(0, &itr);
		r = ctx->Execute();
		if (r != asEXECUTION_FINISHED)
			TEST_FAILED;

		if (bout.buffer != "")
		{
			TEST_FAILED;
			PRINTF("%s", bout.buffer.c_str());
		}

		engine->ShutDownAndRelease();
	}

Am I missing something or should this work?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions