diff --git a/executable_semantics/ast/expression.cpp b/executable_semantics/ast/expression.cpp index 7a7cf0ab85e1..b2e0b070dca7 100644 --- a/executable_semantics/ast/expression.cpp +++ b/executable_semantics/ast/expression.cpp @@ -169,9 +169,8 @@ auto Expression::MakeTupleLiteral(int line_num, for (auto& arg : args) { if (arg.name == "") { if (seen_named_member) { - FatalUserError() - << line_num - << ": positional members must come before named members"; + FATAL_USER_ERROR(line_num) + << "positional members must come before named members"; } arg.name = std::to_string(i); ++i; diff --git a/executable_semantics/common/error.h b/executable_semantics/common/error.h index 8134083c95be..520d852581de 100644 --- a/executable_semantics/common/error.h +++ b/executable_semantics/common/error.h @@ -11,28 +11,53 @@ namespace Carbon { -// Prints an error and exits. This should be used for non-recoverable errors -// with user input. -// -// For example: -// FatalUserError() << "Input is not valid!"; -class FatalUserError { +namespace ErrorInternal { + +// An error-printing stream that exits on destruction. +class ExitingStream { public: - FatalUserError() { llvm::errs() << "ERROR: "; } - ~FatalUserError() { - // Finish with a newline. + // Ends the error with a newline and exits. + LLVM_ATTRIBUTE_NORETURN virtual ~ExitingStream() { llvm::errs() << "\n"; exit(-1); } // Forward output to llvm::errs. template - FatalUserError& operator<<(const T& message) { + ExitingStream& operator<<(const T& message) { llvm::errs() << message; return *this; } }; +} // namespace ErrorInternal + +// Prints an error and exits. This should be used for non-recoverable errors +// with user input. +// +// For example: +// FATAL_USER_ERROR(line_num) << "Line is bad!"; +// FATAL_USER_ERROR_NO_LINE() << "Application is bad!"; +// +// Where possible, try to identify the error as a compilation error or runtime +// error. The generic user error option is provided as a fallback for cases that +// don't fit either of those classifications. + +#define FATAL_USER_ERROR_NO_LINE() ErrorInternal::ExitingStream() << "ERROR: " + +#define FATAL_USER_ERROR(line) FATAL_USER_ERROR_NO_LINE() << line << ": " + +#define FATAL_COMPILATION_ERROR_NO_LINE() \ + ErrorInternal::ExitingStream() << "COMPILATION ERROR: " + +#define FATAL_COMPILATION_ERROR(line) \ + FATAL_COMPILATION_ERROR_NO_LINE() << line << ": " + +#define FATAL_RUNTIME_ERROR_NO_LINE() \ + ErrorInternal::ExitingStream() << "RUNTIME ERROR: " + +#define FATAL_RUNTIME_ERROR(line) FATAL_RUNTIME_ERROR_NO_LINE() << line << ": " + } // namespace Carbon #endif // EXECUTABLE_SEMANTICS_COMMON_ERROR_H_ diff --git a/executable_semantics/common/error_test.cpp b/executable_semantics/common/error_test.cpp index a481da2d3da6..4789ad16e7e3 100644 --- a/executable_semantics/common/error_test.cpp +++ b/executable_semantics/common/error_test.cpp @@ -7,9 +7,31 @@ #include "gtest/gtest.h" namespace Carbon { +namespace { TEST(ErrorTest, FatalUserError) { - ASSERT_DEATH({ FatalUserError() << "test"; }, "ERROR: test\n"); + ASSERT_DEATH({ FATAL_RUNTIME_ERROR_NO_LINE() << "test"; }, "ERROR: test\n"); } +TEST(ErrorTest, FatalRuntimeError) { + ASSERT_DEATH({ FATAL_RUNTIME_ERROR_NO_LINE() << "test"; }, + "RUNTIME ERROR: test\n"); +} + +TEST(ErrorTest, FatalCompilationError) { + ASSERT_DEATH({ FATAL_COMPILATION_ERROR_NO_LINE() << "test"; }, + "COMPILATION ERROR: test\n"); +} + +TEST(ErrorTest, FatalUserErrorLine) { + ASSERT_DEATH({ FATAL_USER_ERROR(1) << "test"; }, "ERROR: 1: test\n"); +} + +auto NoReturnRequired() -> int { FATAL_USER_ERROR_NO_LINE() << "test"; } + +TEST(ErrorTest, NoReturnRequired) { + ASSERT_DEATH({ NoReturnRequired(); }, "ERROR: test\n"); +} + +} // namespace } // namespace Carbon diff --git a/executable_semantics/interpreter/heap.cpp b/executable_semantics/interpreter/heap.cpp index 03a7897f657c..4584121e2e71 100644 --- a/executable_semantics/interpreter/heap.cpp +++ b/executable_semantics/interpreter/heap.cpp @@ -4,6 +4,7 @@ #include "executable_semantics/interpreter/heap.h" +#include "executable_semantics/common/error.h" #include "llvm/ADT/StringExtras.h" namespace Carbon { @@ -33,9 +34,9 @@ void Heap::Write(const Address& a, const Value* v, int line_num) { void Heap::CheckAlive(const Address& address, int line_num) { if (!alive_[address.index]) { - llvm::errs() << line_num << ": undefined behavior: access to dead value " - << *values_[address.index] << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) + << ": undefined behavior: access to dead value " + << *values_[address.index]; } } @@ -44,8 +45,7 @@ void Heap::Deallocate(const Address& address) { if (alive_[address.index]) { alive_[address.index] = false; } else { - llvm::errs() << "runtime error, deallocating an already dead value\n"; - exit(-1); + FATAL_RUNTIME_ERROR_NO_LINE() << "deallocating an already dead value"; } } diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index 244b23df7030..4e6359b80f7a 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -14,6 +14,7 @@ #include "common/check.h" #include "executable_semantics/ast/expression.h" #include "executable_semantics/ast/function_definition.h" +#include "executable_semantics/common/error.h" #include "executable_semantics/common/tracing_flag.h" #include "executable_semantics/interpreter/action.h" #include "executable_semantics/interpreter/frame.h" @@ -185,11 +186,7 @@ void CallFunction(int line_num, std::vector operas, std::optional matches = PatternMatch(operas[0]->GetFunctionValue().param, operas[1], globals, ¶ms, line_num); - if (!matches) { - llvm::errs() - << "internal error in call_function, pattern match failed\n"; - exit(-1); - } + CHECK(matches) << "internal error in call_function, pattern match failed"; // Create the new frame and push it on the stack auto* scope = new Scope(*matches, params); auto* frame = new Frame(operas[0]->GetFunctionValue().name, Stack(scope), @@ -215,19 +212,15 @@ void CallFunction(int line_num, std::vector operas, break; } default: - llvm::errs() << line_num << ": in call, expected a function, not " - << *operas[0] << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) + << "in call, expected a function, not " << *operas[0]; } } void DeallocateScope(int line_num, Scope* scope) { for (const auto& l : scope->locals) { std::optional
a = scope->values.Get(l); - if (!a) { - llvm::errs() << "internal error in DeallocateScope\n"; - exit(-1); - } + CHECK(a); state->heap.Deallocate(*a); } } @@ -277,18 +270,16 @@ auto PatternMatch(const Value* p, const Value* v, Env values, case ValKind::TupleValue: { if (p->GetTupleValue().elements.size() != v->GetTupleValue().elements.size()) { - llvm::errs() - << "runtime error: arity mismatch in tuple pattern match\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) + << "arity mismatch in tuple pattern match"; } for (const TupleElement& pattern_element : p->GetTupleValue().elements) { const Value* value_field = v->GetTupleValue().FindField(pattern_element.name); if (value_field == nullptr) { - llvm::errs() << "runtime error: field " << pattern_element.name - << "not in " << *v << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) + << "field " << pattern_element.name << "not in " << *v; } std::optional matches = PatternMatch( pattern_element.value, value_field, values, vars, line_num); @@ -365,18 +356,16 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) { case ValKind::TupleValue: { if (pat->GetTupleValue().elements.size() != val->GetTupleValue().elements.size()) { - llvm::errs() - << "runtime error: arity mismatch in tuple pattern match\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) + << "arity mismatch in tuple pattern match"; } for (const TupleElement& pattern_element : pat->GetTupleValue().elements) { const Value* value_field = val->GetTupleValue().FindField(pattern_element.name); if (value_field == nullptr) { - llvm::errs() << "runtime error: field " << pattern_element.name - << "not in " << *val << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) + << "field " << pattern_element.name << "not in " << *val; } PatternAssignment(pattern_element.value, value_field, line_num); } @@ -394,13 +383,11 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) { case ValKind::AlternativeValue: { switch (val->tag()) { case ValKind::AlternativeValue: { - if (pat->GetAlternativeValue().choice_name != - val->GetAlternativeValue().choice_name || - pat->GetAlternativeValue().alt_name != - val->GetAlternativeValue().alt_name) { - llvm::errs() << "internal error in pattern assignment\n"; - exit(-1); - } + CHECK(pat->GetAlternativeValue().choice_name == + val->GetAlternativeValue().choice_name && + pat->GetAlternativeValue().alt_name == + val->GetAlternativeValue().alt_name) + << "internal error in pattern assignment"; PatternAssignment(pat->GetAlternativeValue().argument, val->GetAlternativeValue().argument, line_num); break; @@ -415,10 +402,8 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) { break; } default: - if (!ValueEqual(pat, val, line_num)) { - llvm::errs() << "internal error in pattern assignment\n"; - exit(-1); - } + CHECK(ValueEqual(pat, val, line_num)) + << "internal error in pattern assignment"; } } @@ -438,9 +423,9 @@ void StepLvalue() { std::optional
pointer = CurrentEnv(state).Get(exp->GetIdentifierExpression().name); if (!pointer) { - llvm::errs() << exp->line_num << ": could not find `" - << exp->GetIdentifierExpression().name << "`\n"; - exit(-1); + FATAL_RUNTIME_ERROR(exp->line_num) + << ": could not find `" << exp->GetIdentifierExpression().name + << "`"; } const Value* v = Value::MakePointerValue(*pointer); frame->todo.Pop(); @@ -520,8 +505,8 @@ void StepLvalue() { case ExpressionKind::AutoTypeLiteral: case ExpressionKind::ContinuationTypeLiteral: case ExpressionKind::BindingExpression: { - llvm::errs() << "Can't treat expression as lvalue: " << *exp << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR_NO_LINE() + << "Can't treat expression as lvalue: " << *exp; } } } @@ -569,20 +554,16 @@ void StepExp() { std::string f = std::to_string(act->results[1]->GetIntValue()); const Value* field = tuple->GetTupleValue().FindField(f); if (field == nullptr) { - llvm::errs() << "runtime error, field " << f << " not in " - << *tuple << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR_NO_LINE() + << "field " << f << " not in " << *tuple; } frame->todo.Pop(1); frame->todo.Push(Action::MakeValAction(field)); break; } default: - llvm::errs() - << "runtime type error, expected a tuple in field access, " - "not " - << *tuple << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR_NO_LINE() + << "expected a tuple in field access, not " << *tuple; } } break; @@ -636,9 +617,9 @@ void StepExp() { std::optional
pointer = CurrentEnv(state).Get(exp->GetIdentifierExpression().name); if (!pointer) { - llvm::errs() << exp->line_num << ": could not find `" - << exp->GetIdentifierExpression().name << "`\n"; - exit(-1); + FATAL_RUNTIME_ERROR(exp->line_num) + << ": could not find `" << exp->GetIdentifierExpression().name + << "`"; } const Value* pointee = state->heap.Read(*pointer, exp->line_num); frame->todo.Pop(1); @@ -946,12 +927,9 @@ void StepStmt() { std::optional matches = PatternMatch(p, v, frame->scopes.Top()->values, &frame->scopes.Top()->locals, stmt->line_num); - if (!matches) { - llvm::errs() - << stmt->line_num - << ": internal error in variable definition, match failed\n"; - exit(-1); - } + CHECK(matches) + << stmt->line_num + << ": internal error in variable definition, match failed"; frame->scopes.Top()->values = *matches; frame->todo.Pop(1); } @@ -1101,9 +1079,8 @@ void StepStmt() { void Step() { Frame* frame = state->stack.Top(); if (frame->todo.IsEmpty()) { - llvm::errs() << "runtime error: fell off end of function " << frame->name - << " without `return`\n"; - exit(-1); + FATAL_RUNTIME_ERROR_NO_LINE() + << "fell off end of function " << frame->name << " without `return`"; } Action* act = frame->todo.Top(); diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index 753c155b6eae..1c2b09b0e0f7 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/executable_semantics/interpreter/typecheck.cpp @@ -20,18 +20,18 @@ namespace Carbon { void ExpectType(int line_num, const std::string& context, const Value* expected, const Value* actual) { if (!TypeEqual(expected, actual)) { - FatalUserError() << line_num << ": type error in " << context << "\n" - << "expected: " << *expected << "\n" - << "actual: " << *actual; + FATAL_COMPILATION_ERROR(line_num) << "type error in " << context << "\n" + << "expected: " << *expected << "\n" + << "actual: " << *actual; } } void ExpectPointerType(int line_num, const std::string& context, const Value* actual) { if (actual->tag() != ValKind::PointerType) { - FatalUserError() << line_num << ": type error in " << context << "\n" - << "expected a pointer type\n" - << "actual: " << *actual; + FATAL_COMPILATION_ERROR(line_num) << "type error in " << context << "\n" + << "expected a pointer type\n" + << "actual: " << *actual; } } @@ -258,20 +258,13 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, switch (e->tag()) { case ExpressionKind::BindingExpression: { if (context != TCContext::PatternContext) { - llvm::errs() - << e->line_num - << ": compilation error, pattern variables are only allowed in " - "pattern context" - << "\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) + << "pattern variables are only allowed in pattern context"; } auto t = InterpExp(values, e->GetBindingExpression().type); if (t->tag() == ValKind::AutoType) { if (expected == nullptr) { - llvm::errs() << e->line_num - << ": compilation error, auto not allowed here" - << "\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) << " auto not allowed here"; } else { t = expected; } @@ -297,18 +290,15 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, std::string f = std::to_string(i); const Value* field_t = t->GetTupleValue().FindField(f); if (field_t == nullptr) { - llvm::errs() << e->line_num << ": compilation error, field " << f - << " is not in the tuple " << *t << "\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) + << "field " << f << " is not in the tuple " << *t; } auto new_e = Expression::MakeIndexExpression( e->line_num, res.exp, Expression::MakeIntLiteral(e->line_num, i)); return TCResult(new_e, field_t, res.types); } default: - llvm::errs() << e->line_num - << ": compilation error, expected a tuple\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) << "expected a tuple"; } } case ExpressionKind::TupleLiteral: { @@ -316,15 +306,11 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, std::vector arg_types; auto new_types = types; if (expected && expected->tag() != ValKind::TupleValue) { - llvm::errs() << e->line_num - << ": compilation error, didn't expect a tuple\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) << "didn't expect a tuple"; } if (expected && e->GetTupleLiteral().fields.size() != expected->GetTupleValue().elements.size()) { - llvm::errs() << e->line_num - << ": compilation error, tuples of different length\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) << "tuples of different length"; } int i = 0; for (auto arg = e->GetTupleLiteral().fields.begin(); @@ -332,12 +318,10 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, const Value* arg_expected = nullptr; if (expected && expected->tag() == ValKind::TupleValue) { if (expected->GetTupleValue().elements[i].name != arg->name) { - llvm::errs() - << e->line_num - << ": compilation error, field names do not match, expected " + FATAL_COMPILATION_ERROR(e->line_num) + << "field names do not match, expected " << expected->GetTupleValue().elements[i].name << " but got " - << arg->name << "\n"; - exit(-1); + << arg->name; } arg_expected = expected->GetTupleValue().elements[i].value; } @@ -373,11 +357,10 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, return TCResult(new_e, method.second, res.types); } } - llvm::errs() << e->line_num << ": compilation error, struct " - << t->GetStructType().name - << " does not have a field named " - << e->GetFieldAccessExpression().field << "\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) + << "struct " << t->GetStructType().name + << " does not have a field named " + << e->GetFieldAccessExpression().field; case ValKind::TupleValue: for (const TupleElement& field : t->GetTupleValue().elements) { if (e->GetFieldAccessExpression().field == field.name) { @@ -386,11 +369,10 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, return TCResult(new_e, field.value, res.types); } } - llvm::errs() << e->line_num << ": compilation error, struct " - << t->GetStructType().name - << " does not have a field named " - << e->GetFieldAccessExpression().field << "\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) + << "struct " << t->GetStructType().name + << " does not have a field named " + << e->GetFieldAccessExpression().field; case ValKind::ChoiceType: for (auto vt = t->GetChoiceType().alternatives.begin(); vt != t->GetChoiceType().alternatives.end(); ++vt) { @@ -401,18 +383,15 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, return TCResult(new_e, fun_ty, res.types); } } - llvm::errs() << e->line_num << ": compilation error, struct " - << t->GetStructType().name - << " does not have a field named " - << e->GetFieldAccessExpression().field << "\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) + << "struct " << t->GetStructType().name + << " does not have a field named " + << e->GetFieldAccessExpression().field; default: - llvm::errs() - << e->line_num - << ": compilation error in field access, expected a struct\n" - << *e << "\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) + << "field access, expected a struct\n" + << *e; } } case ExpressionKind::IdentifierExpression: { @@ -421,9 +400,8 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, if (type) { return TCResult(e, *type, types); } else { - llvm::errs() << e->line_num << ": could not find `" - << e->GetIdentifierExpression().name << "`\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) + << "could not find `" << e->GetIdentifierExpression().name << "`"; } } case ExpressionKind::IntLiteral: @@ -522,10 +500,9 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, return TCResult(new_e, return_type, arg_res.types); } default: { - llvm::errs() << e->line_num - << ": compilation error in call, expected a function\n" - << *e << "\n"; - exit(-1); + FATAL_COMPILATION_ERROR(e->line_num) + << "in call, expected a function\n" + << *e; } } break; @@ -722,9 +699,8 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num) return Statement::MakeReturn(line_num, Expression::MakeTupleLiteral(line_num, {})); } else { - llvm::errs() - << "control-flow reaches end of non-void function without a return\n"; - exit(-1); + FATAL_COMPILATION_ERROR(line_num) + << "control-flow reaches end of non-void function without a return"; } } switch (stmt->tag()) { @@ -778,11 +754,8 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num) Statement::MakeReturn(stmt->line_num, Expression::MakeTupleLiteral( stmt->line_num, {}))); } else { - llvm::errs() - << stmt->line_num - << ": control-flow reaches end of non-void function without a " - "return\n"; - exit(-1); + FATAL_COMPILATION_ERROR(stmt->line_num) + << "control-flow reaches end of non-void function without a return"; } } } @@ -972,8 +945,8 @@ auto TopLevel(std::list* fs) -> TypeCheckContext { } if (found_main == false) { - llvm::errs() << "error, program must contain a function named `main`\n"; - exit(-1); + FATAL_COMPILATION_ERROR_NO_LINE() + << "program must contain a function named `main`"; } return tops; } diff --git a/executable_semantics/interpreter/value.cpp b/executable_semantics/interpreter/value.cpp index 69090836c6b5..b454d1ecc4d6 100644 --- a/executable_semantics/interpreter/value.cpp +++ b/executable_semantics/interpreter/value.cpp @@ -7,6 +7,7 @@ #include #include "common/check.h" +#include "executable_semantics/common/error.h" #include "llvm/ADT/StringExtras.h" namespace Carbon { @@ -264,24 +265,21 @@ auto GetMember(const Value* v, const std::string& f, int line_num) const Value* field = v->GetStructValue().inits->GetTupleValue().FindField(f); if (field == nullptr) { - llvm::errs() << "runtime error, member " << f << " not in " << *v - << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) << "member " << f << " not in " << *v; } return field; } case ValKind::TupleValue: { const Value* field = v->GetTupleValue().FindField(f); if (field == nullptr) { - llvm::errs() << "field " << f << " not in " << *v << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) << "field " << f << " not in " << *v; } return field; } case ValKind::ChoiceType: { if (FindInVarValues(f, v->GetChoiceType().alternatives) == nullptr) { - llvm::errs() << "alternative " << f << " not in " << *v << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) + << "alternative " << f << " not in " << *v; } return Value::MakeAlternativeConstructorValue(f, v->GetChoiceType().name); } @@ -323,8 +321,8 @@ auto SetFieldImpl(const Value* value, return element.name == *path_begin; }); if (it == elements.end()) { - llvm::errs() << "field " << *path_begin << " not in " << *value << "\n"; - exit(-1); + FATAL_RUNTIME_ERROR(line_num) + << "field " << *path_begin << " not in " << *value; } it->value = SetFieldImpl(it->value, path_begin + 1, path_end, field_value, line_num); diff --git a/executable_semantics/syntax/parse.cpp b/executable_semantics/syntax/parse.cpp index e7f96296e737..7b8dfa1552ba 100644 --- a/executable_semantics/syntax/parse.cpp +++ b/executable_semantics/syntax/parse.cpp @@ -23,8 +23,8 @@ auto parse(const std::string& input_file_name) -> std::variant { yyin = fopen(input_file_name.c_str(), "r"); if (yyin == nullptr) { - FatalUserError() << "Error opening '" << input_file_name - << "': " << std::strerror(errno); + FATAL_USER_ERROR_NO_LINE() << "Error opening '" << input_file_name + << "': " << std::strerror(errno); } std::optional parsed_input = std::nullopt; diff --git a/executable_semantics/testdata/experimental_continuation9.golden b/executable_semantics/testdata/experimental_continuation9.golden index 91c187caa5b0..34549adb493e 100644 --- a/executable_semantics/testdata/experimental_continuation9.golden +++ b/executable_semantics/testdata/experimental_continuation9.golden @@ -1,2 +1,2 @@ -12: undefined behavior: access to dead value 1 +RUNTIME ERROR: 12: : undefined behavior: access to dead value 1 EXIT CODE: 255 diff --git a/executable_semantics/testdata/fun6_fail_type.golden b/executable_semantics/testdata/fun6_fail_type.golden index ee66c8fc753d..5e8611bcad73 100644 --- a/executable_semantics/testdata/fun6_fail_type.golden +++ b/executable_semantics/testdata/fun6_fail_type.golden @@ -1,2 +1,2 @@ -10: compilation error, tuples of different length +COMPILATION ERROR: 10: tuples of different length EXIT CODE: 255 diff --git a/executable_semantics/testdata/generic_function_fail1.golden b/executable_semantics/testdata/generic_function_fail1.golden index ad1dbe684658..95d8c5ec6c97 100644 --- a/executable_semantics/testdata/generic_function_fail1.golden +++ b/executable_semantics/testdata/generic_function_fail1.golden @@ -1,4 +1,4 @@ -ERROR: 10: type error in argument deduction +COMPILATION ERROR: 10: type error in argument deduction expected: Int actual: Bool EXIT CODE: 255 diff --git a/executable_semantics/testdata/generic_function_fail3.golden b/executable_semantics/testdata/generic_function_fail3.golden index 17e479eb57e8..7736dbc51630 100644 --- a/executable_semantics/testdata/generic_function_fail3.golden +++ b/executable_semantics/testdata/generic_function_fail3.golden @@ -1,4 +1,4 @@ -ERROR: 6: type error in addition(1) +COMPILATION ERROR: 6: type error in addition(1) expected: Int actual: T EXIT CODE: 255 diff --git a/executable_semantics/testdata/global_variable3.golden b/executable_semantics/testdata/global_variable3.golden index 15c5091d1cc1..bea966af02b8 100644 --- a/executable_semantics/testdata/global_variable3.golden +++ b/executable_semantics/testdata/global_variable3.golden @@ -1,4 +1,4 @@ -ERROR: 7: type error in initializer of variable +COMPILATION ERROR: 7: type error in initializer of variable expected: Int actual: Bool EXIT CODE: 255 diff --git a/executable_semantics/testdata/global_variable5.golden b/executable_semantics/testdata/global_variable5.golden index bde9af24c422..2957a9e9f596 100644 --- a/executable_semantics/testdata/global_variable5.golden +++ b/executable_semantics/testdata/global_variable5.golden @@ -1,4 +1,4 @@ -ERROR: 10: type error in return +COMPILATION ERROR: 10: type error in return expected: () actual: Int EXIT CODE: 255 diff --git a/executable_semantics/testdata/global_variable8.golden b/executable_semantics/testdata/global_variable8.golden index f7b1ace2d97a..29acb51f3b9b 100644 --- a/executable_semantics/testdata/global_variable8.golden +++ b/executable_semantics/testdata/global_variable8.golden @@ -1,2 +1,2 @@ -8: could not find `y` +RUNTIME ERROR: 8: : could not find `y` EXIT CODE: 255 diff --git a/executable_semantics/testdata/pattern_variable_fail.golden b/executable_semantics/testdata/pattern_variable_fail.golden index b3b6c70aa57e..5e1c441aa198 100644 --- a/executable_semantics/testdata/pattern_variable_fail.golden +++ b/executable_semantics/testdata/pattern_variable_fail.golden @@ -1,2 +1,2 @@ -7: compilation error, pattern variables are only allowed in pattern context +COMPILATION ERROR: 7: pattern variables are only allowed in pattern context EXIT CODE: 255 diff --git a/executable_semantics/testdata/struct_field_access_mismatch.carbon b/executable_semantics/testdata/struct_field_access_mismatch.carbon new file mode 100644 index 000000000000..c4c0ecc62358 --- /dev/null +++ b/executable_semantics/testdata/struct_field_access_mismatch.carbon @@ -0,0 +1,12 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +struct Point { + var x: Int; + var y: Int; +} + +fn main() -> Int { + return Point(.x = 1, .y = 2).z - 1; +} diff --git a/executable_semantics/testdata/struct_field_access_mismatch.golden b/executable_semantics/testdata/struct_field_access_mismatch.golden new file mode 100644 index 000000000000..6e59576746e1 --- /dev/null +++ b/executable_semantics/testdata/struct_field_access_mismatch.golden @@ -0,0 +1,2 @@ +COMPILATION ERROR: 11: struct Point does not have a field named z +EXIT CODE: 255 diff --git a/executable_semantics/testdata/struct_field_mismatch.carbon b/executable_semantics/testdata/struct_field_mismatch.carbon new file mode 100644 index 000000000000..57170f0437eb --- /dev/null +++ b/executable_semantics/testdata/struct_field_mismatch.carbon @@ -0,0 +1,12 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +struct Point { + var x: Int; + var y: Int; +} + +fn main() -> Int { + return Point(.x = 1, .z = 2).x - 1; +} diff --git a/executable_semantics/testdata/struct_field_mismatch.golden b/executable_semantics/testdata/struct_field_mismatch.golden new file mode 100644 index 000000000000..75a6b65694ce --- /dev/null +++ b/executable_semantics/testdata/struct_field_mismatch.golden @@ -0,0 +1,2 @@ +COMPILATION ERROR: 11: field names do not match, expected y but got z +EXIT CODE: 255 diff --git a/executable_semantics/testdata/struct_field_missing.carbon b/executable_semantics/testdata/struct_field_missing.carbon new file mode 100644 index 000000000000..9912bcfd9cd5 --- /dev/null +++ b/executable_semantics/testdata/struct_field_missing.carbon @@ -0,0 +1,12 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +struct Point { + var x: Int; + var y: Int; +} + +fn main() -> Int { + return Point(.x = 1).x - 1; +} diff --git a/executable_semantics/testdata/struct_field_missing.golden b/executable_semantics/testdata/struct_field_missing.golden new file mode 100644 index 000000000000..cd03b9f04642 --- /dev/null +++ b/executable_semantics/testdata/struct_field_missing.golden @@ -0,0 +1,2 @@ +COMPILATION ERROR: 11: tuples of different length +EXIT CODE: 255 diff --git a/executable_semantics/testdata/tuple5.golden b/executable_semantics/testdata/tuple5.golden index 382e3643637f..56845af412d4 100644 --- a/executable_semantics/testdata/tuple5.golden +++ b/executable_semantics/testdata/tuple5.golden @@ -1,4 +1,4 @@ -ERROR: 8: type error in pattern variable +COMPILATION ERROR: 8: type error in pattern variable expected: (x = Int, y = Int) actual: (y = Int, x = Int) EXIT CODE: 255 diff --git a/executable_semantics/testdata/tuple_equality3.golden b/executable_semantics/testdata/tuple_equality3.golden index cbaaabc06399..6cdc4b8eb223 100644 --- a/executable_semantics/testdata/tuple_equality3.golden +++ b/executable_semantics/testdata/tuple_equality3.golden @@ -1,4 +1,4 @@ -ERROR: 8: type error in == +COMPILATION ERROR: 8: type error in == expected: (0 = Int, 1 = Int) actual: (0 = Int) EXIT CODE: 255