Skip to content

Commit

Permalink
Merge pull request #83486 from dalexeev/gds-fix-call-non-static-in-st…
Browse files Browse the repository at this point in the history
…atic-var-lambda

GDScript: Fix non-static call is allowed in static var lambda body
  • Loading branch information
akien-mga committed Oct 20, 2023
2 parents e6e9b04 + 7f4721a commit b075c61
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 17 deletions.
42 changes: 27 additions & 15 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1585,7 +1585,13 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
GDScriptParser::FunctionNode *previous_function = parser->current_function;
parser->current_function = p_function;
bool previous_static_context = static_context;
static_context = p_function->is_static;
if (p_is_lambda) {
// For lambdas this is determined from the context, the `static` keyword is not allowed.
p_function->is_static = static_context;
} else {
// For normal functions, this is determined in the parser by the `static` keyword.
static_context = p_function->is_static;
}

GDScriptParser::DataType prev_datatype = p_function->get_datatype();

Expand Down Expand Up @@ -3317,15 +3323,16 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
}

if (is_self && static_context && !method_flags.has_flag(METHOD_FLAG_STATIC)) {
if (parser->current_function) {
// Get the parent function above any lambda.
GDScriptParser::FunctionNode *parent_function = parser->current_function;
while (parent_function->source_lambda) {
parent_function = parent_function->source_lambda->parent_function;
}
// Get the parent function above any lambda.
GDScriptParser::FunctionNode *parent_function = parser->current_function;
while (parent_function && parent_function->source_lambda) {
parent_function = parent_function->source_lambda->parent_function;
}

if (parent_function) {
push_error(vformat(R"*(Cannot call non-static function "%s()" from static function "%s()".)*", p_call->function_name, parent_function->identifier->name), p_call);
} else {
push_error(vformat(R"*(Cannot call non-static function "%s()" for static variable initializer.)*", p_call->function_name), p_call);
push_error(vformat(R"*(Cannot call non-static function "%s()" from a static variable initializer.)*", p_call->function_name), p_call);
}
} else if (!is_self && base_type.is_meta_type && !method_flags.has_flag(METHOD_FLAG_STATIC)) {
base_type.is_meta_type = false; // For `to_string()`.
Expand Down Expand Up @@ -3908,15 +3915,16 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
bool source_is_variable = p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_VARIABLE || p_identifier->source == GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
bool source_is_signal = p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
if ((source_is_variable || source_is_signal) && static_context) {
if (parser->current_function) {
// Get the parent function above any lambda.
GDScriptParser::FunctionNode *parent_function = parser->current_function;
while (parent_function->source_lambda) {
parent_function = parent_function->source_lambda->parent_function;
}
// Get the parent function above any lambda.
GDScriptParser::FunctionNode *parent_function = parser->current_function;
while (parent_function && parent_function->source_lambda) {
parent_function = parent_function->source_lambda->parent_function;
}

if (parent_function) {
push_error(vformat(R"*(Cannot access %s "%s" from the static function "%s()".)*", source_is_signal ? "signal" : "instance variable", p_identifier->name, parent_function->identifier->name), p_identifier);
} else {
push_error(vformat(R"*(Cannot access %s "%s" for a static variable initializer.)*", source_is_signal ? "signal" : "instance variable", p_identifier->name), p_identifier);
push_error(vformat(R"*(Cannot access %s "%s" from a static variable initializer.)*", source_is_signal ? "signal" : "instance variable", p_identifier->name), p_identifier);
}
}

Expand Down Expand Up @@ -5459,12 +5467,15 @@ void GDScriptAnalyzer::resolve_pending_lambda_bodies() {
}

GDScriptParser::LambdaNode *previous_lambda = current_lambda;
bool previous_static_context = static_context;

List<GDScriptParser::LambdaNode *> lambdas = pending_body_resolution_lambdas;
pending_body_resolution_lambdas.clear();

for (GDScriptParser::LambdaNode *lambda : lambdas) {
current_lambda = lambda;
static_context = lambda->function->is_static;

resolve_function_body(lambda->function, true);

int captures_amount = lambda->captures.size();
Expand Down Expand Up @@ -5493,6 +5504,7 @@ void GDScriptAnalyzer::resolve_pending_lambda_bodies() {
}

current_lambda = previous_lambda;
static_context = previous_static_context;
}

bool GDScriptAnalyzer::class_exists(const StringName &p_class) const {
Expand Down
2 changes: 1 addition & 1 deletion modules/gdscript/gdscript_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,7 @@ class GDScriptParser {
HashMap<StringName, int> parameters_indices;
TypeNode *return_type = nullptr;
SuiteNode *body = nullptr;
bool is_static = false;
bool is_static = false; // For lambdas it's determined in the analyzer.
bool is_coroutine = false;
Variant rpc_config;
MethodInfo info;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# GH-83468

func non_static_func():
pass

static func static_func():
var f := func ():
var g := func ():
non_static_func()
g.call()
f.call()

func test():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static_func()" from static function "static_func()".
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# GH-83468

func non_static_func():
pass

static func static_func(
f := func ():
var g := func ():
non_static_func()
g.call()
):
f.call()

func test():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static_func()" from static function "static_func()".
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# GH-83468

func non_static_func():
pass

static var static_var = func ():
var f := func ():
var g := func ():
non_static_func()
g.call()
f.call()

func test():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static_func()" from a static variable initializer.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# GH-83468

func non_static_func():
pass

static var static_var:
set(_value):
var f := func ():
var g := func ():
non_static_func()
g.call()
f.call()

func test():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static_func()" from static function "@static_var_setter()".
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static()" for static variable initializer.
Cannot call non-static function "non_static()" from a static variable initializer.

0 comments on commit b075c61

Please sign in to comment.