diff --git a/Compiler/script2/cs_parser.cpp b/Compiler/script2/cs_parser.cpp index 93848c84e1..fa177f9968 100644 --- a/Compiler/script2/cs_parser.cpp +++ b/Compiler/script2/cs_parser.cpp @@ -3890,6 +3890,14 @@ void AGS::Parser::ParseExpression(SrcList &src, EvaluationResult &eres) size_t const expr_start = src.GetCursor(); SkipToEndOfExpression(src); SrcList expression = SrcList(src, expr_start, src.GetCursor() - expr_start); + Symbol potential_ident = src.PeekNext(); + if (_sym.IsIdentifier(potential_ident) && + !_sym.IsPredefined(potential_ident) && + _sym.kNoSrcLocation == _sym.GetDeclared(potential_ident)) + { + UserError("Identifier '%s' is undeclared", _sym.GetName(potential_ident).c_str()); + } + if (0u == expression.Length()) UserError("Expected an expression, found '%s' instead", _sym.GetName(src.GetNext()).c_str()); diff --git a/Compiler/test2/cc_parser_test_1.cpp b/Compiler/test2/cc_parser_test_1.cpp index fcc8322c0e..dea01df3a0 100644 --- a/Compiler/test2/cc_parser_test_1.cpp +++ b/Compiler/test2/cc_parser_test_1.cpp @@ -2696,3 +2696,66 @@ TEST_F(Compile1, DynarrayOfArray) { int compileResult = cc_compile(inpl, scrip); ASSERT_STRNE("Ok", (compileResult >= 0) ? "Ok" : last_seen_cc_error()); } + +TEST_F(Compile1, IdentUnknownMessage1) +{ + // When an unknown identifier comes up after an expression, + // complain about that with a specific error message. + + char const *inpl = "\ + int foo () \n\ + { \n\ + int i; \n\ + while (i < Holzschuh) \n\ + {} \n\ + } \n\ + "; + + int compile_result = cc_compile(inpl, scrip); + std::string msg = last_seen_cc_error(); + ASSERT_STRNE("Ok", (compile_result >= 0) ? "Ok" : msg.c_str()); + EXPECT_NE(std::string::npos, msg.find("'Holzschuh'")); + EXPECT_NE(std::string::npos, msg.find("undeclared")); +} + +TEST_F(Compile1, IdentUnknownMessage2) +{ + // When an unknown identifier comes up when an expression is expected, + // complain about that with a specific error message. + + char const *inpl = "\ + int foo () \n\ + { \n\ + int i; \n\ + if (Holzschuh) \n\ + {} \n\ + } \n\ + "; + + int compile_result = cc_compile(inpl, scrip); + std::string msg = last_seen_cc_error(); + ASSERT_STRNE("Ok", (compile_result >= 0) ? "Ok" : msg.c_str()); + EXPECT_NE(std::string::npos, msg.find("'Holzschuh'")); + EXPECT_NE(std::string::npos, msg.find("undeclared")); +} + +TEST_F(Compile1, ExpressionNotFoundMessage2) +{ + // When others come up when an expression is expected, + // complain about that + + char const *inpl = "\ + int foo () \n\ + { \n\ + int i; \n\ + if (do) \n\ + {} \n\ + } \n\ + "; + + int compile_result = cc_compile(inpl, scrip); + std::string msg = last_seen_cc_error(); + ASSERT_STRNE("Ok", (compile_result >= 0) ? "Ok" : msg.c_str()); + EXPECT_NE(std::string::npos, msg.find("an expression")); + EXPECT_NE(std::string::npos, msg.find("'do'")); +}