From 9829f188b7f8b0b31e34bee8b1827131ab34324f Mon Sep 17 00:00:00 2001 From: Jon Meow <46229924+jonmeow@users.noreply.github.com> Date: Mon, 2 Aug 2021 11:08:22 -0700 Subject: [PATCH] Move all new's to global_arena, and remove ASAN disabling (#690) Note this changes identifiers from char* to string to avoid malloc. Fixes #580 --- executable_semantics/BUILD | 8 ---- executable_semantics/ast/BUILD | 10 +---- executable_semantics/ast/member.cpp | 4 +- executable_semantics/ast/pattern.cpp | 9 ++-- executable_semantics/ast/pattern_test.cpp | 17 ++++---- executable_semantics/ast/statement.cpp | 29 +++++++------ executable_semantics/common/arena.h | 2 +- executable_semantics/interpreter/BUILD | 5 +++ executable_semantics/interpreter/action.cpp | 11 ++--- executable_semantics/interpreter/dictionary.h | 4 +- .../interpreter/interpreter.cpp | 35 ++++++++------- .../interpreter/typecheck.cpp | 24 +++++++---- executable_semantics/interpreter/value.cpp | 43 ++++++++++--------- executable_semantics/syntax/BUILD | 1 + executable_semantics/syntax/lexer.lpp | 5 +-- executable_semantics/syntax/parser.ypp | 36 ++++++++-------- .../syntax/syntax_helpers.cpp | 3 +- executable_semantics/tests.py | 4 -- 18 files changed, 130 insertions(+), 120 deletions(-) diff --git a/executable_semantics/BUILD b/executable_semantics/BUILD index d0f8af7d0475..ed0b57fd836c 100644 --- a/executable_semantics/BUILD +++ b/executable_semantics/BUILD @@ -26,10 +26,6 @@ cc_binary( ":executable_semantics", "testdata/%s.carbon" % e, ], - env = { - # TODO(#580): Remove this when leaks are fixed. - "ASAN_OPTIONS": "detect_leaks=0", - }, golden = "testdata/%s.golden" % e, ) for e in TEST_LIST] @@ -49,10 +45,6 @@ test_suite( ":executable_semantics", "testdata/%s.carbon" % e, ], - env = { - # TODO(#580): Remove this when leaks are fixed. - "ASAN_OPTIONS": "detect_leaks=0", - }, golden = "testdata/%s.golden" % e, golden_is_subset = True, ) for e in TEST_LIST] diff --git a/executable_semantics/ast/BUILD b/executable_semantics/ast/BUILD index fc99bc251999..a7e24a4c179e 100644 --- a/executable_semantics/ast/BUILD +++ b/executable_semantics/ast/BUILD @@ -42,10 +42,6 @@ cc_library( cc_test( name = "expression_test", srcs = ["expression_test.cpp"], - env = { - # TODO(#580): Remove this when leaks are fixed. - "ASAN_OPTIONS": "detect_leaks=0", - }, deps = [ ":expression", "//executable_semantics/syntax:paren_contents", @@ -82,6 +78,7 @@ cc_library( deps = [ ":expression", "//common:ostream", + "//executable_semantics/common:arena", "//executable_semantics/common:error", "@llvm-project//llvm:Support", ], @@ -90,10 +87,6 @@ cc_library( cc_test( name = "pattern_test", srcs = ["pattern_test.cpp"], - env = { - # TODO(#580): Remove this when leaks are fixed. - "ASAN_OPTIONS": "detect_leaks=0", - }, deps = [ ":pattern", "//executable_semantics/syntax:paren_contents", @@ -112,6 +105,7 @@ cc_library( ":pattern", "//common:check", "//common:ostream", + "//executable_semantics/common:arena", "@llvm-project//llvm:Support", ], ) diff --git a/executable_semantics/ast/member.cpp b/executable_semantics/ast/member.cpp index b7b14a24f429..293440277cf6 100644 --- a/executable_semantics/ast/member.cpp +++ b/executable_semantics/ast/member.cpp @@ -4,11 +4,13 @@ #include "executable_semantics/ast/member.h" +#include "executable_semantics/common/arena.h" + namespace Carbon { auto Member::MakeFieldMember(int line_num, const BindingPattern* binding) -> Member* { - auto m = new Member(); + auto m = global_arena->New(); m->line_num = line_num; m->value = FieldMember({.binding = binding}); return m; diff --git a/executable_semantics/ast/pattern.cpp b/executable_semantics/ast/pattern.cpp index 2d608a10bbe3..7a429b290bb4 100644 --- a/executable_semantics/ast/pattern.cpp +++ b/executable_semantics/ast/pattern.cpp @@ -8,6 +8,7 @@ #include "common/ostream.h" #include "executable_semantics/ast/expression.h" +#include "executable_semantics/common/arena.h" #include "executable_semantics/common/error.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Casting.h" @@ -57,7 +58,8 @@ TuplePattern::TuplePattern(const Expression* tuple_literal) : Pattern(Kind::TuplePattern, tuple_literal->line_num) { const auto& tuple = tuple_literal->GetTupleLiteral(); for (const FieldInitializer& init : tuple.fields) { - fields.push_back(Field(init.name, new ExpressionPattern(init.expression))); + fields.push_back(Field( + init.name, global_arena->New(init.expression))); } } @@ -75,7 +77,7 @@ auto PatternFromParenContents(int line_num, auto TuplePatternFromParenContents(int line_num, const ParenContents& paren_contents) -> const TuplePattern* { - return new TuplePattern( + return global_arena->New( line_num, paren_contents.TupleElements(line_num)); } @@ -98,7 +100,8 @@ auto ParenExpressionToParenPattern(const ParenContents& contents) .elements = {}, .has_trailing_comma = contents.has_trailing_comma}; for (const auto& element : contents.elements) { result.elements.push_back( - {.name = element.name, .term = new ExpressionPattern(element.term)}); + {.name = element.name, + .term = global_arena->New(element.term)}); } return result; } diff --git a/executable_semantics/ast/pattern_test.cpp b/executable_semantics/ast/pattern_test.cpp index 1c53e5a3a5f8..94bfc0025f62 100644 --- a/executable_semantics/ast/pattern_test.cpp +++ b/executable_semantics/ast/pattern_test.cpp @@ -5,6 +5,7 @@ #include "executable_semantics/ast/pattern.h" #include "executable_semantics/ast/expression.h" +#include "executable_semantics/common/arena.h" #include "executable_semantics/syntax/paren_contents.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -51,7 +52,7 @@ TEST(PatternTest, UnaryNoCommaAsPattern) { // ``` ParenContents contents = { .elements = {{.name = std::nullopt, - .term = new AutoPattern(/*line_num=*/2)}}, + .term = global_arena->New(/*line_num=*/2)}}, .has_trailing_comma = false}; const Pattern* pattern = PatternFromParenContents(/*line_num=*/1, contents); @@ -62,7 +63,7 @@ TEST(PatternTest, UnaryNoCommaAsPattern) { TEST(PatternTest, UnaryNoCommaAsTuplePattern) { ParenContents contents = { .elements = {{.name = std::nullopt, - .term = new AutoPattern(/*line_num=*/2)}}, + .term = global_arena->New(/*line_num=*/2)}}, .has_trailing_comma = false}; const TuplePattern* tuple = @@ -74,7 +75,7 @@ TEST(PatternTest, UnaryNoCommaAsTuplePattern) { TEST(PatternTest, UnaryWithCommaAsPattern) { ParenContents contents = { .elements = {{.name = std::nullopt, - .term = new AutoPattern(/*line_num=*/2)}}, + .term = global_arena->New(/*line_num=*/2)}}, .has_trailing_comma = true}; const Pattern* pattern = PatternFromParenContents(/*line_num=*/1, contents); @@ -87,7 +88,7 @@ TEST(PatternTest, UnaryWithCommaAsPattern) { TEST(PatternTest, UnaryWithCommaAsTuplePattern) { ParenContents contents = { .elements = {{.name = std::nullopt, - .term = new AutoPattern(/*line_num=*/2)}}, + .term = global_arena->New(/*line_num=*/2)}}, .has_trailing_comma = true}; const TuplePattern* tuple = @@ -99,9 +100,9 @@ TEST(PatternTest, UnaryWithCommaAsTuplePattern) { TEST(PatternTest, BinaryAsPattern) { ParenContents contents = { .elements = {{.name = std::nullopt, - .term = new AutoPattern(/*line_num=*/2)}, + .term = global_arena->New(/*line_num=*/2)}, {.name = std::nullopt, - .term = new AutoPattern(/*line_num=*/3)}}, + .term = global_arena->New(/*line_num=*/3)}}, .has_trailing_comma = true}; const Pattern* pattern = PatternFromParenContents(/*line_num=*/1, contents); @@ -114,9 +115,9 @@ TEST(PatternTest, BinaryAsPattern) { TEST(PatternTest, BinaryAsTuplePattern) { ParenContents contents = { .elements = {{.name = std::nullopt, - .term = new AutoPattern(/*line_num=*/2)}, + .term = global_arena->New(/*line_num=*/2)}, {.name = std::nullopt, - .term = new AutoPattern(/*line_num=*/3)}}, + .term = global_arena->New(/*line_num=*/3)}}, .has_trailing_comma = true}; const TuplePattern* tuple = diff --git a/executable_semantics/ast/statement.cpp b/executable_semantics/ast/statement.cpp index 02446b5090be..05cbb0d05573 100644 --- a/executable_semantics/ast/statement.cpp +++ b/executable_semantics/ast/statement.cpp @@ -5,6 +5,7 @@ #include "executable_semantics/ast/statement.h" #include "common/check.h" +#include "executable_semantics/common/arena.h" namespace Carbon { @@ -62,7 +63,7 @@ auto Statement::GetAwait() const -> const Await& { auto Statement::MakeExpressionStatement(int line_num, const Expression* exp) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = ExpressionStatement({.exp = exp}); return s; @@ -70,7 +71,7 @@ auto Statement::MakeExpressionStatement(int line_num, const Expression* exp) auto Statement::MakeAssign(int line_num, const Expression* lhs, const Expression* rhs) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Assign({.lhs = lhs, .rhs = rhs}); return s; @@ -79,7 +80,7 @@ auto Statement::MakeAssign(int line_num, const Expression* lhs, auto Statement::MakeVariableDefinition(int line_num, const Pattern* pat, const Expression* init) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = VariableDefinition({.pat = pat, .init = init}); return s; @@ -88,7 +89,7 @@ auto Statement::MakeVariableDefinition(int line_num, const Pattern* pat, auto Statement::MakeIf(int line_num, const Expression* cond, const Statement* then_stmt, const Statement* else_stmt) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = If({.cond = cond, .then_stmt = then_stmt, .else_stmt = else_stmt}); return s; @@ -96,21 +97,21 @@ auto Statement::MakeIf(int line_num, const Expression* cond, auto Statement::MakeWhile(int line_num, const Expression* cond, const Statement* body) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = While({.cond = cond, .body = body}); return s; } auto Statement::MakeBreak(int line_num) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Break(); return s; } auto Statement::MakeContinue(int line_num) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Continue(); return s; @@ -118,7 +119,7 @@ auto Statement::MakeContinue(int line_num) -> const Statement* { auto Statement::MakeReturn(int line_num, const Expression* e) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Return({.exp = e}); return s; @@ -126,7 +127,7 @@ auto Statement::MakeReturn(int line_num, const Expression* e) auto Statement::MakeSequence(int line_num, const Statement* s1, const Statement* s2) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Sequence({.stmt = s1, .next = s2}); return s; @@ -134,7 +135,7 @@ auto Statement::MakeSequence(int line_num, const Statement* s1, auto Statement::MakeBlock(int line_num, const Statement* stmt) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Block({.stmt = stmt}); return s; @@ -144,7 +145,7 @@ auto Statement::MakeMatch( int line_num, const Expression* exp, std::list>* clauses) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Match({.exp = exp, .clauses = clauses}); return s; @@ -155,7 +156,7 @@ auto Statement::MakeMatch( auto Statement::MakeContinuation(int line_num, std::string continuation_variable, const Statement* body) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Continuation({.continuation_variable = std::move(continuation_variable), @@ -166,7 +167,7 @@ auto Statement::MakeContinuation(int line_num, // Returns an AST node for a run statement give its line number and argument. auto Statement::MakeRun(int line_num, const Expression* argument) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Run({.argument = argument}); return s; @@ -174,7 +175,7 @@ auto Statement::MakeRun(int line_num, const Expression* argument) // Returns an AST node for an await statement give its line number. auto Statement::MakeAwait(int line_num) -> const Statement* { - auto* s = new Statement(); + auto* s = global_arena->New(); s->line_num = line_num; s->value = Await(); return s; diff --git a/executable_semantics/common/arena.h b/executable_semantics/common/arena.h index b1bd68b3c425..b42e4b02c7d8 100644 --- a/executable_semantics/common/arena.h +++ b/executable_semantics/common/arena.h @@ -37,7 +37,7 @@ class Arena { class ArenaEntryTyped : public ArenaEntry { public: template - explicit ArenaEntryTyped(Args&... args) + explicit ArenaEntryTyped(Args&&... args) : instance(std::forward(args)...) {} auto Instance() -> T* { return &instance; } diff --git a/executable_semantics/interpreter/BUILD b/executable_semantics/interpreter/BUILD index a40d659c8ba5..a2955fce1619 100644 --- a/executable_semantics/interpreter/BUILD +++ b/executable_semantics/interpreter/BUILD @@ -17,6 +17,7 @@ cc_library( "//executable_semantics/ast:expression", "//executable_semantics/ast:function_definition", "//executable_semantics/ast:statement", + "//executable_semantics/common:arena", "@llvm-project//llvm:Support", ], ) @@ -97,6 +98,7 @@ cc_library( "//executable_semantics/ast:declaration", "//executable_semantics/ast:expression", "//executable_semantics/ast:function_definition", + "//executable_semantics/common:arena", "//executable_semantics/common:tracing_flag", "@llvm-project//llvm:Support", ], @@ -113,6 +115,7 @@ cc_library( "//executable_semantics/ast:expression", "//executable_semantics/ast:function_definition", "//executable_semantics/ast:statement", + "//executable_semantics/common:arena", "//executable_semantics/common:tracing_flag", "@llvm-project//llvm:Support", ], @@ -129,6 +132,8 @@ cc_library( "//common:ostream", "//executable_semantics/ast:function_definition", "//executable_semantics/ast:statement", + "//executable_semantics/common:arena", + "//executable_semantics/common:error", "@llvm-project//llvm:Support", ], ) diff --git a/executable_semantics/interpreter/action.cpp b/executable_semantics/interpreter/action.cpp index c73161b548c5..dad17615d43a 100644 --- a/executable_semantics/interpreter/action.cpp +++ b/executable_semantics/interpreter/action.cpp @@ -12,37 +12,38 @@ #include "executable_semantics/ast/expression.h" #include "executable_semantics/ast/function_definition.h" +#include "executable_semantics/common/arena.h" #include "executable_semantics/interpreter/stack.h" #include "llvm/ADT/StringExtras.h" namespace Carbon { auto Action::MakeLValAction(const Expression* e) -> Action* { - auto* act = new Action(); + auto* act = global_arena->New(); act->value = LValAction({.exp = e}); return act; } auto Action::MakeExpressionAction(const Expression* e) -> Action* { - auto* act = new Action(); + auto* act = global_arena->New(); act->value = ExpressionAction({.exp = e}); return act; } auto Action::MakePatternAction(const Pattern* p) -> Action* { - auto* act = new Action(); + auto* act = global_arena->New(); act->value = PatternAction({.pattern = p}); return act; } auto Action::MakeStatementAction(const Statement* s) -> Action* { - auto* act = new Action(); + auto* act = global_arena->New(); act->value = StatementAction({.stmt = s}); return act; } auto Action::MakeValAction(const Value* v) -> Action* { - auto* act = new Action(); + auto* act = global_arena->New(); act->value = ValAction({.val = v}); return act; } diff --git a/executable_semantics/interpreter/dictionary.h b/executable_semantics/interpreter/dictionary.h index 4cec806a0984..136d51ee2454 100644 --- a/executable_semantics/interpreter/dictionary.h +++ b/executable_semantics/interpreter/dictionary.h @@ -10,6 +10,7 @@ #include #include +#include "executable_semantics/common/arena.h" #include "executable_semantics/interpreter/list_node.h" namespace Carbon { @@ -37,7 +38,8 @@ class Dictionary { // Associate the value v with key k in the dictionary. // Time complexity: O(1). auto Set(const K& k, const V& v) -> void { - head = new ListNode>(std::make_pair(k, v), head); + head = global_arena->New>>(std::make_pair(k, v), + head); } typedef ListNodeIterator> Iterator; diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index 4e6fc2841fde..9ad47b3a8ae3 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/arena.h" #include "executable_semantics/common/error.h" #include "executable_semantics/common/tracing_flag.h" #include "executable_semantics/interpreter/action.h" @@ -193,10 +194,11 @@ void CallFunction(int line_num, std::vector operas, ¶ms, line_num); 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), - Stack(Action::MakeStatementAction( - operas[0]->GetFunctionValue().body))); + auto* scope = global_arena->New(*matches, params); + auto* frame = global_arena->New( + operas[0]->GetFunctionValue().name, Stack(scope), + Stack( + Action::MakeStatementAction(operas[0]->GetFunctionValue().body))); state->stack.Push(frame); break; } @@ -888,7 +890,7 @@ void StepStmt() { std::optional matches = PatternMatch(pat, v, values, &vars, stmt->line_num); if (matches) { // we have a match, start the body - auto* new_scope = new Scope(*matches, vars); + auto* new_scope = global_arena->New(*matches, vars); frame->scopes.Push(new_scope); const Statement* body_block = Statement::MakeBlock(stmt->line_num, c->second); @@ -959,7 +961,8 @@ void StepStmt() { case StatementKind::Block: { if (act->pos == 0) { if (stmt->GetBlock().stmt) { - auto* scope = new Scope(CurrentEnv(state), {}); + auto* scope = global_arena->New(CurrentEnv(state), + std::list()); frame->scopes.Push(scope); frame->todo.Push(Action::MakeStatementAction(stmt->GetBlock().stmt)); act->pos++; @@ -1085,14 +1088,16 @@ void StepStmt() { CHECK(act->pos == 0); // Create a continuation object by creating a frame similar the // way one is created in a function call. - Scope* scope = new Scope(CurrentEnv(state), std::list()); + Scope* scope = + global_arena->New(CurrentEnv(state), std::list()); Stack scopes; scopes.Push(scope); Stack todo; todo.Push(Action::MakeStatementAction(Statement::MakeReturn( stmt->line_num, Expression::MakeTupleLiteral(stmt->line_num, {})))); todo.Push(Action::MakeStatementAction(stmt->GetContinuation().body)); - Frame* continuation_frame = new Frame("__continuation", scopes, todo); + Frame* continuation_frame = + global_arena->New("__continuation", scopes, todo); Address continuation_address = state->heap.AllocateValue( Value::MakeContinuationValue({continuation_frame})); // Store the continuation's address in the frame. @@ -1176,7 +1181,7 @@ void Step() { // Interpret the whole porogram. auto InterpProgram(std::list* fs) -> int { - state = new State(); // Runtime state. + state = global_arena->New(); // Runtime state. if (tracing_output) { llvm::outs() << "********** initializing globals **********\n"; } @@ -1186,8 +1191,8 @@ auto InterpProgram(std::list* fs) -> int { const Expression* call_main = Expression::MakeCallExpression( 0, Expression::MakeIdentifierExpression(0, "main"), arg); auto todo = Stack(Action::MakeExpressionAction(call_main)); - auto* scope = new Scope(globals, std::list()); - auto* frame = new Frame("top", Stack(scope), todo); + auto* scope = global_arena->New(globals, std::list()); + auto* frame = global_arena->New("top", Stack(scope), todo); state->stack = Stack(frame); if (tracing_output) { @@ -1209,8 +1214,8 @@ auto InterpProgram(std::list* fs) -> int { // Interpret an expression at compile-time. auto InterpExp(Env values, const Expression* e) -> const Value* { auto todo = Stack(Action::MakeExpressionAction(e)); - auto* scope = new Scope(values, std::list()); - auto* frame = new Frame("InterpExp", Stack(scope), todo); + auto* scope = global_arena->New(values, std::list()); + auto* frame = global_arena->New("InterpExp", Stack(scope), todo); state->stack = Stack(frame); while (state->stack.Count() > 1 || state->stack.Top()->todo.Count() > 1 || @@ -1224,8 +1229,8 @@ auto InterpExp(Env values, const Expression* e) -> const Value* { // Interpret a pattern at compile-time. auto InterpPattern(Env values, const Pattern* p) -> const Value* { auto todo = Stack(Action::MakePatternAction(p)); - auto* scope = new Scope(values, std::list()); - auto* frame = new Frame("InterpPattern", Stack(scope), todo); + auto* scope = global_arena->New(values, std::list()); + auto* frame = global_arena->New("InterpPattern", Stack(scope), todo); state->stack = Stack(frame); while (state->stack.Count() > 1 || state->stack.Top()->todo.Count() > 1 || diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index afede2623823..006dbff5c2ae 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/executable_semantics/interpreter/typecheck.cpp @@ -12,6 +12,7 @@ #include "common/ostream.h" #include "executable_semantics/ast/function_definition.h" +#include "executable_semantics/common/arena.h" #include "executable_semantics/common/error.h" #include "executable_semantics/common/tracing_flag.h" #include "executable_semantics/interpreter/interpreter.h" @@ -512,9 +513,10 @@ auto TypeCheckPattern(const Pattern* p, TypeEnv types, Env values, FATAL_COMPILATION_ERROR(binding.LineNumber()) << "Unsupported type pattern"; } - auto new_p = new BindingPattern( + auto new_p = global_arena->New( binding.LineNumber(), binding.Name(), - new ExpressionPattern(ReifyType(type, binding.LineNumber()))); + global_arena->New( + ReifyType(type, binding.LineNumber()))); if (binding.Name().has_value()) { types.Set(*binding.Name(), type); } @@ -553,7 +555,8 @@ auto TypeCheckPattern(const Pattern* p, TypeEnv types, Env values, TuplePattern::Field(field.name, field_result.pattern)); field_types.push_back({.name = field.name, .value = field_result.type}); } - auto new_tuple = new TuplePattern(tuple.LineNumber(), new_fields); + auto new_tuple = + global_arena->New(tuple.LineNumber(), new_fields); auto tuple_t = Value::MakeTupleValue(std::move(field_types)); return {.pattern = new_tuple, .type = tuple_t, .types = new_types}; } @@ -578,7 +581,7 @@ auto TypeCheckPattern(const Pattern* p, TypeEnv types, Env values, } TCPattern arg_results = TypeCheckPattern(alternative.Arguments(), types, values, parameter_types); - return {.pattern = new AlternativePattern( + return {.pattern = global_arena->New( alternative.LineNumber(), ReifyType(choice_type, alternative.LineNumber()), alternative.AlternativeName(), @@ -589,7 +592,7 @@ auto TypeCheckPattern(const Pattern* p, TypeEnv types, Env values, case Pattern::Kind::ExpressionPattern: { TCExpression result = TypeCheckExp(cast(p)->Expression(), types, values); - return {.pattern = new ExpressionPattern(result.exp), + return {.pattern = global_arena->New(result.exp), .type = result.type, .types = result.types}; } @@ -622,7 +625,8 @@ auto TypeCheckStmt(const Statement* s, TypeEnv types, Env values, auto res = TypeCheckExp(s->GetMatch().exp, types, values); auto res_type = res.type; auto new_clauses = - new std::list>(); + global_arena + ->New>>(); for (auto& clause : *s->GetMatch().clauses) { new_clauses->push_back(TypecheckCase( res_type, clause.first, clause.second, types, values, ret_type)); @@ -748,7 +752,8 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num) switch (stmt->tag()) { case StatementKind::Match: { auto new_clauses = - new std::list>(); + global_arena + ->New>>(); for (auto i = stmt->GetMatch().clauses->begin(); i != stmt->GetMatch().clauses->end(); ++i) { auto s = CheckOrEnsureReturn(i->second, void_return, stmt->line_num); @@ -827,9 +832,10 @@ auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values) auto res = TypeCheckStmt(f->body, param_res.types, values, return_type); bool void_return = TypeEqual(return_type, Value::MakeUnitTypeVal()); auto body = CheckOrEnsureReturn(res.stmt, void_return, f->line_num); - return new FunctionDefinition( + return global_arena->New( f->line_num, f->name, f->deduced_parameters, f->param_pattern, - new ExpressionPattern(ReifyType(return_type, f->line_num)), body); + global_arena->New(ReifyType(return_type, f->line_num)), + body); } auto TypeOfFunDef(TypeEnv types, Env values, const FunctionDefinition* fun_def) diff --git a/executable_semantics/interpreter/value.cpp b/executable_semantics/interpreter/value.cpp index b454d1ecc4d6..86bbc8022235 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/arena.h" #include "executable_semantics/common/error.h" #include "llvm/ADT/StringExtras.h" @@ -111,47 +112,47 @@ auto TupleValue::FindField(const std::string& name) const -> const Value* { } auto Value::MakeIntValue(int i) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = IntValue({.value = i}); return v; } auto Value::MakeBoolValue(bool b) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = BoolValue({.value = b}); return v; } auto Value::MakeFunctionValue(std::string name, const Value* param, const Statement* body) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = FunctionValue({.name = std::move(name), .param = param, .body = body}); return v; } auto Value::MakePointerValue(Address addr) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = PointerValue({.value = addr}); return v; } auto Value::MakeStructValue(const Value* type, const Value* inits) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = StructValue({.type = type, .inits = inits}); return v; } auto Value::MakeTupleValue(std::vector elements) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = TupleValue({.elements = std::move(elements)}); return v; } auto Value::MakeAlternativeValue(std::string alt_name, std::string choice_name, const Value* argument) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = AlternativeValue({.alt_name = std::move(alt_name), .choice_name = std::move(choice_name), .argument = argument}); @@ -161,7 +162,7 @@ auto Value::MakeAlternativeValue(std::string alt_name, std::string choice_name, auto Value::MakeAlternativeConstructorValue(std::string alt_name, std::string choice_name) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = AlternativeConstructorValue( {.alt_name = std::move(alt_name), .choice_name = std::move(choice_name)}); return v; @@ -170,45 +171,45 @@ auto Value::MakeAlternativeConstructorValue(std::string alt_name, // Return a first-class continuation represented a fragment // of the stack. auto Value::MakeContinuationValue(std::vector stack) -> Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = ContinuationValue({.stack = std::move(stack)}); return v; } auto Value::MakeBindingPlaceholderValue(std::optional name, const Value* type) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = BindingPlaceholderValue({.name = std::move(name), .type = type}); return v; } auto Value::MakeIntType() -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = IntType(); return v; } auto Value::MakeBoolType() -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = BoolType(); return v; } auto Value::MakeTypeType() -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = TypeType(); return v; } // Return a Continuation type. auto Value::MakeContinuationType() -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = ContinuationType(); return v; } auto Value::MakeAutoType() -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = AutoType(); return v; } @@ -216,21 +217,21 @@ auto Value::MakeAutoType() -> const Value* { auto Value::MakeFunctionType(std::vector deduced_params, const Value* param, const Value* ret) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = FunctionType( {.deduced = std::move(deduced_params), .param = param, .ret = ret}); return v; } auto Value::MakePointerType(const Value* type) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = PointerType({.type = type}); return v; } auto Value::MakeStructType(std::string name, VarValues fields, VarValues methods) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = StructType({.name = std::move(name), .fields = std::move(fields), .methods = std::move(methods)}); @@ -238,20 +239,20 @@ auto Value::MakeStructType(std::string name, VarValues fields, } auto Value::MakeUnitTypeVal() -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = TupleValue({.elements = {}}); return v; } auto Value::MakeChoiceType(std::string name, VarValues alts) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = ChoiceType({.name = std::move(name), .alternatives = std::move(alts)}); return v; } auto Value::MakeVariableType(std::string name) -> const Value* { - auto* v = new Value(); + auto* v = global_arena->New(); v->value = VariableType({.name = std::move(name)}); return v; } diff --git a/executable_semantics/syntax/BUILD b/executable_semantics/syntax/BUILD index 62e7fe5109d8..e48972ea286d 100644 --- a/executable_semantics/syntax/BUILD +++ b/executable_semantics/syntax/BUILD @@ -33,6 +33,7 @@ cc_library( "//common:ostream", "//executable_semantics/ast:declaration", "//executable_semantics/ast:expression", + "//executable_semantics/common:arena", "//executable_semantics/common:error", "//executable_semantics/common:tracing_flag", "//executable_semantics/interpreter", diff --git a/executable_semantics/syntax/lexer.lpp b/executable_semantics/syntax/lexer.lpp index 09c651e760a5..10e2894d43b1 100644 --- a/executable_semantics/syntax/lexer.lpp +++ b/executable_semantics/syntax/lexer.lpp @@ -178,10 +178,7 @@ operator and its operand, leading to three more cases: {identifier} { BEGIN(AFTER_OPERAND); - int n = strlen(yytext); - auto r = reinterpret_cast(malloc((n + 1) * sizeof(char))); - strncpy(r, yytext, n + 1); - return yy::parser::make_identifier(r, context.current_token_position); + return yy::parser::make_identifier(yytext, context.current_token_position); } {integer_literal} { diff --git a/executable_semantics/syntax/parser.ypp b/executable_semantics/syntax/parser.ypp index 23482c0ef403..920150c0e89f 100644 --- a/executable_semantics/syntax/parser.ypp +++ b/executable_semantics/syntax/parser.ypp @@ -63,6 +63,7 @@ #include "executable_semantics/ast/expression.h" #include "executable_semantics/ast/function_definition.h" #include "executable_semantics/ast/pattern.h" +#include "executable_semantics/common/arena.h" #include "executable_semantics/syntax/paren_contents.h" namespace Carbon { @@ -82,8 +83,8 @@ void yy::parser::error(const location_type&, const std::string& message) { } // %code %token integer_literal -%token identifier -%type designator +%token identifier +%type designator %type declaration %type function_declaration %type function_definition @@ -310,17 +311,17 @@ pattern: non_expression_pattern { $$ = $1; } | expression - { $$ = new Carbon::ExpressionPattern($1); } + { $$ = Carbon::global_arena->New($1); } ; non_expression_pattern: AUTO - { $$ = new Carbon::AutoPattern(yylineno); } + { $$ = Carbon::global_arena->New(yylineno); } | binding_lhs ":" pattern - { $$ = new Carbon::BindingPattern(yylineno, $1, $3); } + { $$ = Carbon::global_arena->New(yylineno, $1, $3); } | paren_pattern { $$ = $1; } | expression tuple_pattern - { $$ = new Carbon::AlternativePattern(yylineno, $1, $2); } + { $$ = Carbon::global_arena->New(yylineno, $1, $2); } ; binding_lhs: identifier { $$ = $1; } @@ -354,7 +355,7 @@ paren_pattern_contents: | paren_pattern_contents "," paren_expression_element { $$ = $1; - $$.elements.push_back({.name = $3.name, .term = new Carbon::ExpressionPattern($3.term)}); + $$.elements.push_back({.name = $3.name, .term = Carbon::global_arena->New($3.term)}); } | paren_pattern_contents "," paren_pattern_element { @@ -376,24 +377,25 @@ tuple_pattern: paren_pattern_base // rules out the possibility of an `expression` at this point. maybe_empty_tuple_pattern: "(" ")" - { $$ = new Carbon::TuplePattern(yylineno, {}); } + { $$ = Carbon::global_arena->New(yylineno, std::vector()); } | tuple_pattern { $$ = $1; } ; clause: CASE pattern DBLARROW statement - { $$ = new std::pair($2, $4); } + { $$ = Carbon::global_arena->New>($2, $4); } | DEFAULT DBLARROW statement { - auto vp = new Carbon::BindingPattern( - yylineno, std::nullopt, new Carbon::AutoPattern(yylineno)); - $$ = new std::pair(vp, $3); + auto vp = Carbon::global_arena->New( + yylineno, std::nullopt, Carbon::global_arena->New(yylineno)); + $$ = Carbon::global_arena->New>(vp, $3); } ; clause_list: // Empty { - $$ = new std::list>(); + $$ = Carbon::global_arena->New>>(); } | clause clause_list { $$ = $2; $$->push_front(*$1); } @@ -484,13 +486,13 @@ function_definition: FN identifier deduced_params maybe_empty_tuple_pattern return_type block { $$ = Carbon::FunctionDefinition( - yylineno, $2, $3, $4, new Carbon::ExpressionPattern($5), $6); + yylineno, $2, $3, $4, Carbon::global_arena->New($5), $6); } | FN identifier deduced_params maybe_empty_tuple_pattern DBLARROW expression ";" { $$ = Carbon::FunctionDefinition( yylineno, $2, $3, $4, - new Carbon::AutoPattern(yylineno), + Carbon::global_arena->New(yylineno), Carbon::Statement::MakeReturn(yylineno, $6)); } ; @@ -498,10 +500,10 @@ function_declaration: FN identifier deduced_params maybe_empty_tuple_pattern return_type ";" { $$ = Carbon::FunctionDefinition( - yylineno, $2, $3, $4, new Carbon::ExpressionPattern($5), 0); } + yylineno, $2, $3, $4, Carbon::global_arena->New($5), 0); } ; variable_declaration: identifier ":" pattern - { $$ = new Carbon::BindingPattern(yylineno, $1, $3); } + { $$ = Carbon::global_arena->New(yylineno, $1, $3); } ; member: VAR variable_declaration ";" { $$ = Carbon::Member::MakeFieldMember(yylineno, $2); } diff --git a/executable_semantics/syntax/syntax_helpers.cpp b/executable_semantics/syntax/syntax_helpers.cpp index 9eb9da1354d9..da8ae39eeba7 100644 --- a/executable_semantics/syntax/syntax_helpers.cpp +++ b/executable_semantics/syntax/syntax_helpers.cpp @@ -5,6 +5,7 @@ #include "executable_semantics/syntax/syntax_helpers.h" #include "common/ostream.h" +#include "executable_semantics/common/arena.h" #include "executable_semantics/common/tracing_flag.h" #include "executable_semantics/interpreter/interpreter.h" #include "executable_semantics/interpreter/typecheck.h" @@ -19,7 +20,7 @@ void ExecProgram(std::list* fs) { } llvm::outs() << "********** type checking **********\n"; } - state = new State(); // Compile-time state. + state = global_arena->New(); // Compile-time state. TypeCheckContext p = TopLevel(fs); TypeEnv top = p.types; Env ct_top = p.values; diff --git a/executable_semantics/tests.py b/executable_semantics/tests.py index b56ce5bb511c..bc40b4744d60 100755 --- a/executable_semantics/tests.py +++ b/executable_semantics/tests.py @@ -111,9 +111,6 @@ def _update_list(use_git_state): def _update_golden(test): """Updates the golden file for `test` by running executable_semantics.""" - # TODO(#580): Remove this when leaks are fixed. - env = os.environ.copy() - env["ASAN_OPTIONS"] = "detect_leaks=0" # Invoke the test update directly in order to allow parallel execution # (`bazel run` will serialize). p = subprocess.run( @@ -123,7 +120,6 @@ def _update_golden(test): "%s/executable_semantics %s/%s.carbon" % (_BINDIR, _TESTDATA, test), "--update", ], - env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, )