Fix some memory leaks and add comment in Parser.cc

This commit is contained in:
Sam Vervaeck 2023-05-27 20:57:43 +02:00
parent 8e4fae2228
commit 3efd2a6d6a
Signed by: samvv
SSH key fingerprint: SHA256:dIg0ywU1OP+ZYifrYxy8c5esO72cIKB+4/9wkZj1VaY

View file

@ -12,6 +12,23 @@
#include "bolt/Diagnostics.hpp" #include "bolt/Diagnostics.hpp"
#include "bolt/DiagnosticEngine.hpp" #include "bolt/DiagnosticEngine.hpp"
// ## Some rules
//
// 1. Only Tokens.get() if you are certain the token is valid. If not, you
// should first Tokens.peek() and only call Tokens.get() if all checks
// succeeded.
//
// 2. Do not consume a token when emitting an error. It is up to
// skipToLineFoldEnd() to skip the actual tokens. Because that function skips
// over blocks, it is important it knows when a block started.
//
// 3. Always unref() whatever CST node that has been allocated on error. That
// includes tokens. This avoids memory leaks. And yes, they matter when the
// compiler is permanently on such as in a language server.
//
// 5. Always unref() a LineFoldEnd obtained via Tokens.get(), since it will
// never be stored somewhere
namespace bolt { namespace bolt {
std::optional<OperatorInfo> OperatorTable::getInfix(Token* T) { std::optional<OperatorInfo> OperatorTable::getInfix(Token* T) {
@ -648,7 +665,7 @@ finish:
Then.push_back(Element); Then.push_back(Element);
} }
} }
Tokens.get(); // Always a LineFoldEnd Tokens.get()->unref(); // Always a LineFoldEnd
Parts.push_back(new IfStatementPart(IfKeyword, Test, T1, Then)); Parts.push_back(new IfStatementPart(IfKeyword, Test, T1, Then));
auto T3 = Tokens.peek(); auto T3 = Tokens.peek();
if (T3->getKind() == NodeKind::ElseKeyword) { if (T3->getKind() == NodeKind::ElseKeyword) {
@ -672,7 +689,7 @@ finish:
Else.push_back(Element); Else.push_back(Element);
} }
} }
Tokens.get(); // Always a LineFoldEnd Tokens.get()->unref(); // Always a LineFoldEnd
Parts.push_back(new IfStatementPart(T3, nullptr, T4, Else)); Parts.push_back(new IfStatementPart(T3, nullptr, T4, Else));
} }
return new IfStatement(Parts); return new IfStatement(Parts);
@ -1035,7 +1052,7 @@ after_vars:
Elements.push_back(Element); Elements.push_back(Element);
} }
} }
Tokens.get(); // Always a LineFoldEnd Tokens.get()->unref(); // Always a LineFoldEnd
return new ClassDeclaration( return new ClassDeclaration(
PubKeyword, PubKeyword,
ClassKeyword, ClassKeyword,
@ -1204,7 +1221,7 @@ after_vars:
void Parser::checkLineFoldEnd() { void Parser::checkLineFoldEnd() {
auto T0 = Tokens.peek(); auto T0 = Tokens.peek();
if (T0->getKind() == NodeKind::LineFoldEnd) { if (T0->getKind() == NodeKind::LineFoldEnd) {
Tokens.get(); Tokens.get()->unref();
} else { } else {
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector { NodeKind::LineFoldEnd }); DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector { NodeKind::LineFoldEnd });
skipToLineFoldEnd(); skipToLineFoldEnd();