From 3490c8d2f3897a581154d1e08b5ef443d658f47c Mon Sep 17 00:00:00 2001 From: Kyle Marek-Spartz Date: Fri, 9 Jan 2015 15:14:06 -0600 Subject: [PATCH 1/2] Segfault when calling super at top-level with no arguments. If enclosingClass is null, we can't proceed with compilation since we don't have its name. --- src/wren_compiler.c | 38 +++++++++++++++--------------- test/super/super_at_top_level.wren | 1 + 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/wren_compiler.c b/src/wren_compiler.c index 9a41c980..8c79b32a 100644 --- a/src/wren_compiler.c +++ b/src/wren_compiler.c @@ -1835,28 +1835,28 @@ static void super_(Compiler* compiler, bool allowAssignment) else if (enclosingClass->isStaticMethod) { error(compiler, "Cannot use 'super' in a static method."); - } + } else { + loadThis(compiler); - loadThis(compiler); + // TODO: Super operator calls. - // TODO: Super operator calls. + // See if it's a named super call, or an unnamed one. + if (match(compiler, TOKEN_DOT)) + { + // Compile the superclass call. + consume(compiler, TOKEN_NAME, "Expect method name after 'super.'."); + namedCall(compiler, allowAssignment, CODE_SUPER_0); + } + else + { + // No explicit name, so use the name of the enclosing method. + char name[MAX_METHOD_SIGNATURE]; + int length = enclosingClass->methodLength; + strncpy(name, enclosingClass->methodName, length); - // See if it's a named super call, or an unnamed one. - if (match(compiler, TOKEN_DOT)) - { - // Compile the superclass call. - consume(compiler, TOKEN_NAME, "Expect method name after 'super.'."); - namedCall(compiler, allowAssignment, CODE_SUPER_0); - } - else - { - // No explicit name, so use the name of the enclosing method. - char name[MAX_METHOD_SIGNATURE]; - int length = enclosingClass->methodLength; - strncpy(name, enclosingClass->methodName, length); - - // Call the superclass method with the same name. - methodCall(compiler, CODE_SUPER_0, name, length); + // Call the superclass method with the same name. + methodCall(compiler, CODE_SUPER_0, name, length); + } } } diff --git a/test/super/super_at_top_level.wren b/test/super/super_at_top_level.wren index 4efe0ea6..d0a997d6 100644 --- a/test/super/super_at_top_level.wren +++ b/test/super/super_at_top_level.wren @@ -1 +1,2 @@ super.foo // expect error +super // expect error From c376d88e61c293b80feb494fb08bea0c896224c6 Mon Sep 17 00:00:00 2001 From: Kyle Marek-Spartz Date: Sun, 11 Jan 2015 17:43:51 -0600 Subject: [PATCH 2/2] super at top level: Allow the compiler to continue compilation after erroring. Added two more tests. --- src/wren_compiler.c | 44 ++++++++++++++++++------------ test/super/super_at_top_level.wren | 2 ++ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/wren_compiler.c b/src/wren_compiler.c index 8c79b32a..79fea9b1 100644 --- a/src/wren_compiler.c +++ b/src/wren_compiler.c @@ -1835,28 +1835,36 @@ static void super_(Compiler* compiler, bool allowAssignment) else if (enclosingClass->isStaticMethod) { error(compiler, "Cannot use 'super' in a static method."); - } else { - loadThis(compiler); + } - // TODO: Super operator calls. + loadThis(compiler); - // See if it's a named super call, or an unnamed one. - if (match(compiler, TOKEN_DOT)) - { - // Compile the superclass call. - consume(compiler, TOKEN_NAME, "Expect method name after 'super.'."); - namedCall(compiler, allowAssignment, CODE_SUPER_0); - } - else - { - // No explicit name, so use the name of the enclosing method. - char name[MAX_METHOD_SIGNATURE]; - int length = enclosingClass->methodLength; + // TODO: Super operator calls. + + // See if it's a named super call, or an unnamed one. + if (match(compiler, TOKEN_DOT)) + { + // Compile the superclass call. + consume(compiler, TOKEN_NAME, "Expect method name after 'super.'."); + namedCall(compiler, allowAssignment, CODE_SUPER_0); + } + else + { + // No explicit name, so use the name of the enclosing method. + char name[MAX_METHOD_SIGNATURE]; + int length; + if (enclosingClass != NULL) { + length = enclosingClass->methodLength; strncpy(name, enclosingClass->methodName, length); - - // Call the superclass method with the same name. - methodCall(compiler, CODE_SUPER_0, name, length); + } else { + // The compiler errored since super is called outside a method. + // We want to continue, but we cannot generate valid bytecode. + length = 0; + strncpy(name, "", length); } + + // Call the superclass method with the same name. + methodCall(compiler, CODE_SUPER_0, name, length); } } diff --git a/test/super/super_at_top_level.wren b/test/super/super_at_top_level.wren index d0a997d6..eb2b1252 100644 --- a/test/super/super_at_top_level.wren +++ b/test/super/super_at_top_level.wren @@ -1,2 +1,4 @@ super.foo // expect error super // expect error +super.foo("bar") // expect error +super("foo") // expect error