From 058eede181c51dfcf6b973d157331637c67e26ca Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Wed, 8 Jan 2025 12:29:09 +0100 Subject: [PATCH 01/13] Drop redundant string copy. --- spicy/toolchain/src/config.cc.in | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/spicy/toolchain/src/config.cc.in b/spicy/toolchain/src/config.cc.in index de9f59121..f41f9b837 100644 --- a/spicy/toolchain/src/config.cc.in +++ b/spicy/toolchain/src/config.cc.in @@ -99,13 +99,11 @@ void Configuration::init(bool use_build_directory) { std::vector library_paths; - if ( auto path = std::getenv("SPICY_PATH") ) { - library_paths = - hilti::util::transform(hilti::util::split(path, ":"), [](auto s) { return std::string(std::move(s)); }); - } - else { + if ( auto path = std::getenv("SPICY_PATH") ) + library_paths = hilti::util::split(path, ":"); + + else library_paths = flatten({".", prefix("${SPICY_CONFIG_LIBRARY_DIRS}", "", installation_tag)}); - } spicy_library_paths = hilti::util::transform(library_paths, [](const auto& s) { return hilti::rt::filesystem::path(s); }); From 9d6554690c436e67ffd222743f14c98c4bbb29aa Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Wed, 8 Jan 2025 12:41:35 +0100 Subject: [PATCH 02/13] Add missing `break` in `switch` case. --- hilti/toolchain/src/compiler/optimizer.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hilti/toolchain/src/compiler/optimizer.cc b/hilti/toolchain/src/compiler/optimizer.cc index 8e48df0ba..da8926ad3 100644 --- a/hilti/toolchain/src/compiler/optimizer.cc +++ b/hilti/toolchain/src/compiler/optimizer.cc @@ -1341,6 +1341,8 @@ class FeatureRequirementsVisitor : public visitor::MutatingPreOrder { // Collect feature requirements associated with type. for ( const auto& requirement : n->attributes()->findAll(hilti::attribute::Kind::RequiresTypeFeature) ) _features[n->typeID()][*requirement->valueAsString()] = true; + + break; } case Stage::TRANSFORM: { From 2b8769755b0bfe5a83fe03129be661503079872d Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Wed, 8 Jan 2025 12:42:29 +0100 Subject: [PATCH 03/13] Clearly mark up unreachable code. --- hilti/toolchain/src/compiler/driver.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hilti/toolchain/src/compiler/driver.cc b/hilti/toolchain/src/compiler/driver.cc index 6e268da76..14bc25758 100644 --- a/hilti/toolchain/src/compiler/driver.cc +++ b/hilti/toolchain/src/compiler/driver.cc @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -745,9 +746,7 @@ Result Driver::run() { return result::Error(fmt("uncaught exception of type %s: %s", util::demangle(typeid(e).name()), e.what())); } - _ctx = nullptr; - - return {}; + util::cannotBeReached(); } Result Driver::compile() { From 996b7262815537f3fff5cb3a5818459f5b42dcfd Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Wed, 8 Jan 2025 13:53:09 +0100 Subject: [PATCH 04/13] Prevent division by zero which is UB. --- hilti/toolchain/src/ast/ast-context.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hilti/toolchain/src/ast/ast-context.cc b/hilti/toolchain/src/ast/ast-context.cc index 1c2cf3a99..8140f2afe 100644 --- a/hilti/toolchain/src/ast/ast-context.cc +++ b/hilti/toolchain/src/ast/ast-context.cc @@ -918,7 +918,7 @@ void ASTContext::_dumpStats(const logging::DebugStream& stream, std::string_view logger().debugPushIndent(stream); for ( const auto& [type, num] : live_by_type ) { - if ( static_cast(num) / static_cast(live) > 0.01 ) + if ( live != 0 && static_cast(num) / static_cast(live) > 0.01 ) HILTI_DEBUG(stream, fmt("- %s: %" PRIu64, type, num)); } logger().debugPopIndent(stream); From a8a6e224aa151fded5c1bf8b02eee6639838813f Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Wed, 8 Jan 2025 13:55:36 +0100 Subject: [PATCH 05/13] Prevent copies in various places. This patch removes copies in different places by e.g., leveraging const lifetime expansion or move semantics. We also clean up getters to return new values less often. --- hilti/runtime/src/types/regexp.cc | 2 +- hilti/runtime/src/types/stream.cc | 2 +- hilti/toolchain/include/ast/types/name.h | 2 +- hilti/toolchain/src/ast/ast-context.cc | 2 +- hilti/toolchain/src/ast/declarations/field.cc | 2 +- hilti/toolchain/src/ast/node.cc | 5 +- hilti/toolchain/src/ast/operator-registry.cc | 2 +- hilti/toolchain/src/ast/operators/bitfield.cc | 2 +- hilti/toolchain/src/ast/operators/generic.cc | 4 +- hilti/toolchain/src/ast/operators/struct.cc | 3 +- hilti/toolchain/src/ast/operators/tuple.cc | 5 +- hilti/toolchain/src/ast/operators/union.cc | 4 +- hilti/toolchain/src/ast/scope.cc | 2 +- hilti/toolchain/src/base/util.cc | 2 +- .../toolchain/src/compiler/codegen/codegen.cc | 16 +-- .../src/compiler/codegen/coercions.cc | 2 +- hilti/toolchain/src/compiler/codegen/ctors.cc | 2 +- .../src/compiler/codegen/expressions.cc | 4 +- .../src/compiler/codegen/operators.cc | 22 ++--- .../src/compiler/codegen/statements.cc | 24 ++--- hilti/toolchain/src/compiler/codegen/types.cc | 27 ++--- .../toolchain/src/compiler/codegen/unpack.cc | 9 +- hilti/toolchain/src/compiler/coercer.cc | 4 +- hilti/toolchain/src/compiler/cxx/linker.cc | 6 +- hilti/toolchain/src/compiler/cxx/unit.cc | 2 +- hilti/toolchain/src/compiler/driver.cc | 4 +- hilti/toolchain/src/compiler/jit.cc | 6 +- hilti/toolchain/src/compiler/optimizer.cc | 10 +- hilti/toolchain/src/compiler/resolver.cc | 8 +- hilti/toolchain/src/compiler/type-unifier.cc | 2 +- hilti/toolchain/src/compiler/unit.cc | 2 +- hilti/toolchain/src/compiler/validator.cc | 2 +- spicy/runtime/src/driver.cc | 5 +- spicy/runtime/src/parser.cc | 2 +- spicy/toolchain/src/ast/operators/unit.cc | 4 +- .../toolchain/src/compiler/codegen/codegen.cc | 2 +- .../toolchain/src/compiler/codegen/grammar.cc | 6 +- .../src/compiler/codegen/parser-builder.cc | 99 ++++++++++--------- .../src/compiler/codegen/parsers/literals.cc | 32 +++--- .../src/compiler/codegen/parsers/types.cc | 24 ++--- .../src/compiler/codegen/unit-builder.cc | 6 +- spicy/toolchain/src/compiler/driver.cc | 2 +- spicy/toolchain/src/compiler/resolver.cc | 17 ++-- spicy/toolchain/src/compiler/validator.cc | 2 +- 44 files changed, 197 insertions(+), 195 deletions(-) diff --git a/hilti/runtime/src/types/regexp.cc b/hilti/runtime/src/types/regexp.cc index c58f6c906..90309f8bc 100644 --- a/hilti/runtime/src/types/regexp.cc +++ b/hilti/runtime/src/types/regexp.cc @@ -265,7 +265,7 @@ void regexp::detail::CompiledRegExp::_compileOne(std::string pattern, int idx) { } RegExp::RegExp(const std::vector& patterns, regexp::Flags flags) { - auto key = (patterns.empty() ? std::string() : join(patterns, "|") + "|" + flags.cacheKey()); + const auto& key = (patterns.empty() ? std::string() : join(patterns, "|") + "|" + flags.cacheKey()); auto& ptr = detail::globalState()->regexp_cache[key]; if ( ! ptr ) diff --git a/hilti/runtime/src/types/stream.cc b/hilti/runtime/src/types/stream.cc index f24c56a8e..577aebea0 100644 --- a/hilti/runtime/src/types/stream.cc +++ b/hilti/runtime/src/types/stream.cc @@ -251,7 +251,7 @@ View View::advanceToNextData() const { // If the position is already not in a gap we can directly compute a view at it. if ( c && ! c->isGap() ) - return View(i, _end); + return View(std::move(i), _end); std::optional last_end; // Offset of the end of the last seen chunk. diff --git a/hilti/toolchain/include/ast/types/name.h b/hilti/toolchain/include/ast/types/name.h index d69221432..f0c1c9868 100644 --- a/hilti/toolchain/include/ast/types/name.h +++ b/hilti/toolchain/include/ast/types/name.h @@ -51,7 +51,7 @@ class Name : public UnqualifiedType { node::Properties properties() const final { auto p = node::Properties{{"id", _id}, {"builtin", _builtin}, {"resolved-type", to_string(_resolved_type_index)}}; - return UnqualifiedType::properties() + p; + return UnqualifiedType::properties() + std::move(p); } static auto create(ASTContext* ctx, const ID& id, Meta meta = {}) { diff --git a/hilti/toolchain/src/ast/ast-context.cc b/hilti/toolchain/src/ast/ast-context.cc index 8140f2afe..daaf2415a 100644 --- a/hilti/toolchain/src/ast/ast-context.cc +++ b/hilti/toolchain/src/ast/ast-context.cc @@ -869,7 +869,7 @@ void ASTContext::_dumpState(const logging::DebugStream& stream) { auto n = _types_by_index[idx]; assert(n->isRetained()); - auto id = n->typeID() ? n->typeID() : ID(""); + const auto& id = n->typeID() ? n->typeID() : ID(""); HILTI_DEBUG(stream, fmt("[%s] %s [%s] (%s)", ast::TypeIndex(idx), id, n->typename_(), n->location().dump(true))); } diff --git a/hilti/toolchain/src/ast/declarations/field.cc b/hilti/toolchain/src/ast/declarations/field.cc index 1d663e8dd..4cf3f961e 100644 --- a/hilti/toolchain/src/ast/declarations/field.cc +++ b/hilti/toolchain/src/ast/declarations/field.cc @@ -10,7 +10,7 @@ using namespace hilti::declaration; node::Properties declaration::Field::properties() const { auto p = node::Properties{{"cc", _cc ? to_string(*_cc) : ""}, {"linked-type", to_string(_linked_type_index)}}; - return Declaration::properties() + p; + return Declaration::properties() + std::move(p); } std::string declaration::Field::_dump() const { diff --git a/hilti/toolchain/src/ast/node.cc b/hilti/toolchain/src/ast/node.cc index a94ae7c45..58eb82086 100644 --- a/hilti/toolchain/src/ast/node.cc +++ b/hilti/toolchain/src/ast/node.cc @@ -64,9 +64,10 @@ std::string Node::renderSelf(bool include_location) const { if ( ! props.empty() ) sprops = util::fmt(" <%s>", util::join(props, " ")); - auto location = (include_location && meta().location()) ? util::fmt(" (%s)", meta().location().dump(true)) : ""; + const auto& location = + (include_location && meta().location()) ? util::fmt(" (%s)", meta().location().dump(true)) : ""; auto no_inherit_scope = (inheritScope() ? "" : " (no-inherit-scope)"); - auto parent = (_parent ? util::fmt(" [parent %s]", identity(_parent)) : " [no parent]"); + const auto& parent = (_parent ? util::fmt(" [parent %s]", identity(_parent)) : " [no parent]"); auto s = util::fmt("%s%s%s%s%s", name(this), sprops, parent, no_inherit_scope, location); diff --git a/hilti/toolchain/src/ast/operator-registry.cc b/hilti/toolchain/src/ast/operator-registry.cc index 27323f0f1..035c0aa34 100644 --- a/hilti/toolchain/src/ast/operator-registry.cc +++ b/hilti/toolchain/src/ast/operator-registry.cc @@ -36,7 +36,7 @@ void Registry::initPending(Builder* builder) { if ( op->hasOperands() ) { // only register if to be instantiated by the resolver through its operands _operators_by_kind[op->kind()].push_back(op.get()); if ( op->kind() == Kind::MemberCall ) { - auto id = op->signature().operands->op1()->type()->type()->as()->id(); + const auto& id = op->signature().operands->op1()->type()->type()->as()->id(); _operators_by_method[id].push_back(op.get()); } diff --git a/hilti/toolchain/src/ast/operators/bitfield.cc b/hilti/toolchain/src/ast/operators/bitfield.cc index e160dd1f6..6f0002290 100644 --- a/hilti/toolchain/src/ast/operators/bitfield.cc +++ b/hilti/toolchain/src/ast/operators/bitfield.cc @@ -28,7 +28,7 @@ QualifiedType* _itemType(Builder* builder, const Expressions& operands) { } void _checkName(expression::ResolvedOperator* op) { - auto id = op->op1()->as()->id(); + const auto& id = op->op1()->as()->id(); if ( ! op->op0()->type()->type()->as()->bits(id) ) op->addError(util::fmt("bitfield type does not have attribute '%s'", id)); } diff --git a/hilti/toolchain/src/ast/operators/generic.cc b/hilti/toolchain/src/ast/operators/generic.cc index 486a895ee..e2028ded6 100644 --- a/hilti/toolchain/src/ast/operators/generic.cc +++ b/hilti/toolchain/src/ast/operators/generic.cc @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -202,7 +201,8 @@ class Unpack : public Operator { else if ( data_type->isA() ) { if ( args.size() >= 2 && args.size() <= 3 ) { auto arg1 = args[1]->type()->type()->cxxID(); - auto arg2 = (args.size() > 2 ? args[2]->type()->type()->cxxID() : ID("::hilti::rt::integer::BitOrder")); + const auto& arg2 = + (args.size() > 2 ? args[2]->type()->type()->cxxID() : ID("::hilti::rt::integer::BitOrder")); if ( arg1 && arg1 == ID("::hilti::rt::ByteOrder") && arg2 && arg2 == ID("::hilti::rt::integer::BitOrder") ) return; diff --git a/hilti/toolchain/src/ast/operators/struct.cc b/hilti/toolchain/src/ast/operators/struct.cc index b479884bf..154a98d28 100644 --- a/hilti/toolchain/src/ast/operators/struct.cc +++ b/hilti/toolchain/src/ast/operators/struct.cc @@ -1,7 +1,6 @@ // Copyright (c) 2021-2023 by the Zeek Project. See LICENSE for details. #include -#include #include #include @@ -59,7 +58,7 @@ QualifiedType* _itemType(Builder* builder, const Expressions& operands) { } void _checkName(expression::ResolvedOperator* op, bool check_optional = false) { - auto id = op->op1()->as()->id(); + const auto& id = op->op1()->as()->id(); auto t = op->op0()->type()->type(); if ( auto x = t->tryAs() ) diff --git a/hilti/toolchain/src/ast/operators/tuple.cc b/hilti/toolchain/src/ast/operators/tuple.cc index 92e9546a7..b9398fd4c 100644 --- a/hilti/toolchain/src/ast/operators/tuple.cc +++ b/hilti/toolchain/src/ast/operators/tuple.cc @@ -1,6 +1,5 @@ // Copyright (c) 2021-2023 by the Zeek Project. See LICENSE for details. -#include #include #include @@ -119,7 +118,7 @@ class Member : public Operator { } QualifiedType* result(Builder* builder, const Expressions& operands, const Meta& meta) const final { - auto id = operands[1]->as()->id(); + const auto& id = operands[1]->as()->id(); auto tt = operands[0]->type()->type()->tryAs(); if ( ! tt ) return builder->qualifiedType(builder->typeUnknown(), Constness::Const); @@ -132,7 +131,7 @@ class Member : public Operator { } void validate(expression::ResolvedOperator* n) const final { - auto id = n->op1()->as()->id(); + const auto& id = n->op1()->as()->id(); auto tt = n->op0()->type()->type()->tryAs(); if ( ! tt ) { n->addError("unknown tuple element"); diff --git a/hilti/toolchain/src/ast/operators/union.cc b/hilti/toolchain/src/ast/operators/union.cc index dc69dd6ff..5497a916e 100644 --- a/hilti/toolchain/src/ast/operators/union.cc +++ b/hilti/toolchain/src/ast/operators/union.cc @@ -1,7 +1,5 @@ // Copyright (c) 2021-2023 by the Zeek Project. See LICENSE for details. -#include -#include #include #include @@ -25,7 +23,7 @@ QualifiedType* itemType(Builder* builder, const Expressions& operands) { } void checkName(expression::ResolvedOperator* op) { - auto id = op->op1()->as()->id(); + const auto& id = op->op1()->as()->id(); if ( ! op->op0()->type()->type()->as()->field(id) ) op->addError(util::fmt("type does not have field '%s'", id)); } diff --git a/hilti/toolchain/src/ast/scope.cc b/hilti/toolchain/src/ast/scope.cc index dc738c2f0..ce2be9047 100644 --- a/hilti/toolchain/src/ast/scope.cc +++ b/hilti/toolchain/src/ast/scope.cc @@ -84,7 +84,7 @@ std::vector Scope::_findID(const Scope* scope, const ID& id, boo std::string nt; std::tie(h, nt) = util::rsplit1(h, "::"); - t = (! t.empty() && ! nt.empty() && t != "$ $" ? util::fmt("%s::%s", nt, t) : nt); + t = (! t.empty() && ! nt.empty() && t != "$ $" ? util::fmt("%s::%s", nt, t) : std::move(nt)); } } diff --git a/hilti/toolchain/src/base/util.cc b/hilti/toolchain/src/base/util.cc index f1e8fdabe..18ae294ce 100644 --- a/hilti/toolchain/src/base/util.cc +++ b/hilti/toolchain/src/base/util.cc @@ -47,7 +47,7 @@ std::vector util::split(std::string s, const std::string& delim) { // FIXME: Don't understand why directly assigning to s doesn't work. std::string t = s.substr(p + delim.size(), std::string::npos); - s = t; + s = std::move(t); } l.push_back(s); diff --git a/hilti/toolchain/src/compiler/codegen/codegen.cc b/hilti/toolchain/src/compiler/codegen/codegen.cc index 2457f5b3e..8006d39df 100644 --- a/hilti/toolchain/src/compiler/codegen/codegen.cc +++ b/hilti/toolchain/src/compiler/codegen/codegen.cc @@ -93,7 +93,7 @@ struct GlobalsVisitor : hilti::visitor::PostOrder { body.addStatement("return ::hilti::rt::detail::moduleGlobals<__globals_t>(__globals_index)"); auto body_decl = cxx::declaration::Function(cxx::declaration::Function::Free, "auto", {ns, "__globals"}, {}, - "static", cxx::declaration::Function::Inline(), body); + "static", cxx::declaration::Function::Inline(), std::move(body)); unit->add(body_decl); } @@ -136,7 +136,7 @@ struct GlobalsVisitor : hilti::visitor::PostOrder { cg->popCxxBlock(); - auto body_decl = cxx::declaration::Function(cxx::declaration::Function::Free, "void", id, + auto body_decl = cxx::declaration::Function(cxx::declaration::Function::Free, "void", std::move(id), {{"ctx", "::hilti::rt::Context*"}}, "extern", std::move(body)); unit->add(body_decl); } @@ -160,7 +160,7 @@ struct GlobalsVisitor : hilti::visitor::PostOrder { body.addStatement(fmt("::%s.reset();", g.id)); } - auto body_decl = cxx::declaration::Function(cxx::declaration::Function::Free, "void", id, + auto body_decl = cxx::declaration::Function(cxx::declaration::Function::Free, "void", std::move(id), {{"ctx", "::hilti::rt::Context*"}}, "extern", std::move(body)); unit->add(body_decl); } @@ -283,7 +283,7 @@ struct GlobalsVisitor : hilti::visitor::PostOrder { auto id_class = n->id().sub(-2); auto id_local = n->id().sub(-1); - auto id_struct_type = (id_module != current_module ? ID(id_module, id_class) : id_class); + const auto& id_struct_type = (id_module != current_module ? ID(id_module, id_class) : id_class); cxx::ID cid; if ( ! is_hook ) { @@ -335,7 +335,7 @@ struct GlobalsVisitor : hilti::visitor::PostOrder { // Adapt the function we generate. d.linkage = "extern"; - d.id = id_hook_impl; + d.id = std::move(id_hook_impl); d.ftype = cxx::declaration::Function::Free; // TODO(robin): This should compile the struct type, not hardcode @@ -586,14 +586,14 @@ struct GlobalsVisitor : hilti::visitor::PostOrder { // Add a call to this to the module's initialization code. cxx::Block call_init_func; call_init_func.addStatement(fmt("%s()", d.id)); - cg->unit()->addInitialization(call_init_func); + cg->unit()->addInitialization(std::move(call_init_func)); } if ( n->linkage() == declaration::Linkage::PreInit ) { // Add a call to this to the module's pre-initialization code. cxx::Block call_preinit_func; call_preinit_func.addStatement(fmt("%s()", d.id)); - cg->unit()->addPreInitialization(call_preinit_func); + cg->unit()->addPreInitialization(std::move(call_preinit_func)); } } } @@ -860,7 +860,7 @@ cxx::Expression CodeGen::unsignedIntegerToBitfield(type::Bitfield* t, const cxx: auto x = fmt("::hilti::rt::integer::bits(%s, %d, %d, %s)", value, b->lower(), b->upper(), bitorder); if ( auto a = b->attributes()->find(hilti::attribute::Kind::Convert) ) { - pushDollarDollar(x); + pushDollarDollar(std::move(x)); bits.emplace_back(compile(*a->valueAsExpression())); popDollarDollar(); } diff --git a/hilti/toolchain/src/compiler/codegen/coercions.cc b/hilti/toolchain/src/compiler/codegen/coercions.cc index ce254bf93..a410c02c6 100644 --- a/hilti/toolchain/src/compiler/codegen/coercions.cc +++ b/hilti/toolchain/src/compiler/codegen/coercions.cc @@ -317,7 +317,7 @@ cxx::Expression CodeGen::coerce(const cxx::Expression& e, QualifiedType* src, Qu return e; auto v = Visitor(this, e, src, dst); - if ( auto nt = hilti::visitor::dispatch(v, src->type(), [](const auto& v) { return v.result; }) ) + if ( auto nt = hilti::visitor::dispatch(v, src->type(), [](const auto& v) -> const auto& { return v.result; }) ) return *nt; logger().internalError(fmt("codegen: type %s unhandled for coercion", src->type()->typename_())); diff --git a/hilti/toolchain/src/compiler/codegen/ctors.cc b/hilti/toolchain/src/compiler/codegen/ctors.cc index 45c7d5ef8..37dfd872d 100644 --- a/hilti/toolchain/src/compiler/codegen/ctors.cc +++ b/hilti/toolchain/src/compiler/codegen/ctors.cc @@ -340,7 +340,7 @@ struct Visitor : hilti::visitor::PreOrder { cxx::Expression CodeGen::compile(Ctor* c, bool lhs) { auto v = Visitor(this); - if ( auto x = hilti::visitor::dispatch(v, c, [](const auto& v) { return v.result; }) ) + if ( auto x = hilti::visitor::dispatch(v, c, [](const auto& v) -> const auto& { return v.result; }) ) return lhs ? _makeLhs(*x, c->type()) : *x; logger().internalError(fmt("ctor %s failed to compile", c->typename_()), c); diff --git a/hilti/toolchain/src/compiler/codegen/expressions.cc b/hilti/toolchain/src/compiler/codegen/expressions.cc index 2f100e17c..d8213d3e3 100644 --- a/hilti/toolchain/src/compiler/codegen/expressions.cc +++ b/hilti/toolchain/src/compiler/codegen/expressions.cc @@ -149,7 +149,7 @@ struct Visitor : hilti::visitor::PreOrder { } auto decl = n->resolvedDeclaration(); - auto fqid = decl->fullyQualifiedID(); + const auto& fqid = decl->fullyQualifiedID(); assert(fqid); if ( decl->isA() ) { @@ -251,7 +251,7 @@ struct Visitor : hilti::visitor::PreOrder { cxx::Expression CodeGen::compile(Expression* e, bool lhs) { auto v = Visitor(this, lhs); - if ( auto x = hilti::visitor::dispatch(v, e, [](const auto& v) { return v.result; }) ) + if ( auto x = hilti::visitor::dispatch(v, e, [](const auto& v) -> const auto& { return v.result; }) ) return lhs ? _makeLhs(*x, e->type()) : *x; logger().internalError(fmt("expression failed to compile ('%s' / %s)", *e, e->typename_()), e); diff --git a/hilti/toolchain/src/compiler/codegen/operators.cc b/hilti/toolchain/src/compiler/codegen/operators.cc index adb9604fd..1ed41fd6a 100644 --- a/hilti/toolchain/src/compiler/codegen/operators.cc +++ b/hilti/toolchain/src/compiler/codegen/operators.cc @@ -110,14 +110,14 @@ struct Visitor : hilti::visitor::PreOrder { /// Bitfield void operator()(operator_::bitfield::Member* n) final { - auto id = n->op1()->as()->id(); + const auto& id = n->op1()->as()->id(); auto elem = n->op0()->type()->type()->as()->bitsIndex(id); assert(elem); result = {fmt("(::hilti::rt::optional::value(std::get<%u>(%s.value)))", *elem, op0(n)), Side::RHS}; } void operator()(operator_::bitfield::HasMember* n) final { - auto id = n->op1()->as()->id(); + const auto& id = n->op1()->as()->id(); auto elem = n->op0()->type()->type()->as()->bitsIndex(id); assert(elem); result = {fmt("std::get<%u>(%s.value).has_value()", *elem, op0(n)), Side::RHS}; @@ -195,7 +195,7 @@ struct Visitor : hilti::visitor::PreOrder { std::string x; if ( auto side = optionalArgument(args, 1); ! side.empty() ) - x = side; + x = std::move(side); if ( auto set = optionalArgument(args, 0); ! set.empty() ) { if ( x.size() ) @@ -843,7 +843,7 @@ struct Visitor : hilti::visitor::PreOrder { cxx::Expression structMember(const expression::ResolvedOperator* o) { const auto& op0 = o->op0(); - auto id = o->op1()->as()->id(); + const auto& id = o->op1()->as()->id(); auto attr = memberAccess(o, id); auto type = op0->type()->type(); @@ -866,7 +866,7 @@ struct Visitor : hilti::visitor::PreOrder { return fmt("::hilti::rt::optional::value(%s)", attr); } - return {attr, Side::LHS}; + return {std::move(attr), Side::LHS}; } void operator()(operator_::struct_::MemberConst* n) final { result = structMember(n); } @@ -879,7 +879,7 @@ struct Visitor : hilti::visitor::PreOrder { auto ft = fdecl->type()->type()->as(); auto args = n->op2()->as()->ctor()->as()->value(); - auto id = n->op1()->as()->id(); + const auto& id = n->op1()->as()->id(); std::vector> zipped; @@ -898,7 +898,7 @@ struct Visitor : hilti::visitor::PreOrder { } void operator()(operator_::struct_::HasMember* n) final { - auto id = n->op1()->as()->id(); + const auto& id = n->op1()->as()->id(); if ( auto f = n->op0()->type()->type()->as()->field(id); f->isOptional() ) result = fmt("%s.has_value()", memberAccess(n, id)); @@ -907,7 +907,7 @@ struct Visitor : hilti::visitor::PreOrder { } void operator()(operator_::struct_::TryMember* n) final { - auto id = n->op1()->as()->id(); + const auto& id = n->op1()->as()->id(); assert(! lhs); if ( auto f = n->op0()->type()->type()->as()->field(id); f->isOptional() ) { @@ -930,7 +930,7 @@ struct Visitor : hilti::visitor::PreOrder { /// Union unsigned int unionFieldIndex(Expression* op0, Expression* op1) { - auto id = op1->as()->id(); + const auto& id = op1->as()->id(); return op0->type()->type()->as()->index(id); } @@ -1103,7 +1103,7 @@ struct Visitor : hilti::visitor::PreOrder { } void operator()(operator_::tuple::Member* n) final { - auto id = n->op1()->as()->id(); + const auto& id = n->op1()->as()->id(); auto elem = n->op0()->type()->type()->as()->elementByID(id); assert(elem); result = {fmt("std::get<%u>(%s)", elem->first, op0(n)), Side::LHS}; @@ -1293,7 +1293,7 @@ struct Visitor : hilti::visitor::PreOrder { cxx::Expression CodeGen::compile(expression::ResolvedOperator* o, bool lhs) { auto v = Visitor(this, lhs); - if ( auto x = hilti::visitor::dispatch(v, o, [](const auto& v) { return v.result; }) ) + if ( auto x = hilti::visitor::dispatch(v, o, [](const auto& v) -> const auto& { return v.result; }) ) return lhs ? _makeLhs(*x, o->type()) : *x; std::cerr << o->dump(); diff --git a/hilti/toolchain/src/compiler/codegen/statements.cc b/hilti/toolchain/src/compiler/codegen/statements.cc index 19a08f4c2..4c688c018 100644 --- a/hilti/toolchain/src/compiler/codegen/statements.cc +++ b/hilti/toolchain/src/compiler/codegen/statements.cc @@ -153,7 +153,7 @@ struct Visitor : hilti::visitor::PreOrder { } auto l = cxx::declaration::Local(cxx::ID(d->id()), cg->compile(d->type(), codegen::TypeUsage::Storage), - std::move(args), init); + std::move(args), std::move(init)); block->addLocal(l); } @@ -187,14 +187,14 @@ struct Visitor : hilti::visitor::PreOrder { if ( ! init.empty() && ! cond.empty() ) head = fmt("%s; %s", init, cond); else if ( ! init.empty() ) - head = init; + head = std::move(init); else - head = cond; + head = std::move(cond); if ( ! n->false_() ) - block->addIf(head, cg->compile(n->true_())); + block->addIf(std::move(head), cg->compile(n->true_())); else - block->addIf(head, cg->compile(n->true_()), cg->compile(n->false_())); + block->addIf(std::move(head), cg->compile(n->true_()), cg->compile(n->false_())); } void operator()(statement::For* n) final { @@ -258,11 +258,11 @@ struct Visitor : hilti::visitor::PreOrder { auto body = cg->compile(c->body()); if ( first ) { - block->addIf(fmt("%s %s = %s", cxx_type, cxx_id, cxx_init), cond, body); + block->addIf(fmt("%s %s = %s", cxx_type, cxx_id, cxx_init), std::move(cond), body); first = false; } else - block->addElseIf(cond, body); + block->addElseIf(std::move(cond), std::move(body)); } cxx::Block default_; @@ -272,7 +272,7 @@ struct Visitor : hilti::visitor::PreOrder { else default_.addStatement( fmt("throw ::hilti::rt::UnhandledSwitchCase(::hilti::rt::to_string_for_print(%s), \"%s\")", - (first ? cxx_init : cxx_id), n->meta().location())); + (first ? cxx_init : std::move(cxx_id)), n->meta().location())); if ( first ) block->addBlock(std::move(default_)); @@ -338,9 +338,9 @@ struct Visitor : hilti::visitor::PreOrder { else_.addStatement("break"); if ( n->condition() || ! init ) - inner_wrapper.addIf(fmt("! (%s)", cg->compile(n->condition())), else_); + inner_wrapper.addIf(fmt("! (%s)", cg->compile(n->condition())), std::move(else_)); else - inner_wrapper.addIf(fmt("! %s", init->id()), else_); + inner_wrapper.addIf(fmt("! %s", init->id()), std::move(else_)); inner_wrapper.appendFromBlock(cg->compile(n->body())); @@ -356,7 +356,7 @@ struct Visitor : hilti::visitor::PreOrder { } outer_wrapper.addWhile(cxx::Expression("true"), inner_wrapper); - block->addBlock(outer_wrapper); + block->addBlock(std::move(outer_wrapper)); return; } @@ -389,7 +389,7 @@ struct Visitor : hilti::visitor::PreOrder { else // C++ doesn't support having both init and cond in a while-loop. // Use a for-loop instead. - block->addFor(sinit, cond, "", body); + block->addFor(std::move(sinit), std::move(cond), "", body); } void operator()(statement::Yield* n) final { diff --git a/hilti/toolchain/src/compiler/codegen/types.cc b/hilti/toolchain/src/compiler/codegen/types.cc index bc6fc7bd1..9e94aa0ca 100644 --- a/hilti/toolchain/src/compiler/codegen/types.cc +++ b/hilti/toolchain/src/compiler/codegen/types.cc @@ -98,8 +98,8 @@ struct VisitorDeclaration : hilti::visitor::PreOrder { else default_ = cg->typeDefaultValue(p->type()); - auto arg = cxx::declaration::Argument(cxx::ID(fmt("__p_%s", p->id())), type, std::move(default_), - internal_type); + auto arg = cxx::declaration::Argument(cxx::ID(fmt("__p_%s", p->id())), std::move(type), + std::move(default_), std::move(internal_type)); args.emplace_back(std::move(arg)); } @@ -234,8 +234,8 @@ struct VisitorDeclaration : hilti::visitor::PreOrder { // Do not pass a default value here since initialization of // the member happens (and needs to happen) via the ctor // block above to guarantee we have a block. - auto x = - cxx::declaration::Local(cxx::ID(f->id()), t, {}, {}, (f->isStatic() ? "inline static" : "")); + auto x = cxx::declaration::Local(cxx::ID(f->id()), std::move(t), {}, {}, + (f->isStatic() ? "inline static" : "")); fields.emplace_back(std::move(x)); @@ -289,12 +289,12 @@ struct VisitorDeclaration : hilti::visitor::PreOrder { std::vector fields; for ( const auto& f : n->fields() ) { auto t = cg->compile(f->type(), codegen::TypeUsage::Storage); - auto x = cxx::declaration::Local(cxx::ID(f->id()), t); + auto x = cxx::declaration::Local(cxx::ID(f->id()), std::move(t)); fields.emplace_back(std::move(x)); } auto t = cxx::type::Union{.members = std::move(fields), .type_name = cxx::ID(id.local())}; - result = cxx::declaration::Type(id, t); + result = cxx::declaration::Type(std::move(id), t); } void operator()(type::Vector* n) final { @@ -314,7 +314,7 @@ struct VisitorDeclaration : hilti::visitor::PreOrder { auto id = cxx::ID(scope, sid); auto labels = util::transform(n->labels(), [](auto l) { return std::make_pair(cxx::ID(l->id()), l->value()); }); auto t = cxx::type::Enum{.labels = std::move(labels), .type_name = cxx::ID(id.local())}; - auto decl = cxx::declaration::Type(id, t, {}, true); + auto decl = cxx::declaration::Type(std::move(id), t, {}, true); dependencies.push_back(decl); result = decl; } @@ -978,7 +978,7 @@ struct VisitorTypeInfoDynamic : hilti::visitor::PreOrder { cxx::Type CodeGen::compile(QualifiedType* t, codegen::TypeUsage usage) { auto v = VisitorStorage(this, t, &_cache_types_storage, usage); - auto x = hilti::visitor::dispatch(v, t->type(), [](const auto& v) { return v.result; }); + auto x = hilti::visitor::dispatch(v, t->type(), [](const auto& v) -> const auto& { return v.result; }); if ( ! x ) { std::cerr << t->dump(); logger().internalError(fmt("codegen: type %s does not have a visitor", *t), t); @@ -1068,7 +1068,7 @@ cxx::Type CodeGen::compile(QualifiedType* t, codegen::TypeUsage usage) { std::optional CodeGen::typeDefaultValue(hilti::QualifiedType* t) { auto v = VisitorStorage(this, t, &_cache_types_storage, codegen::TypeUsage::None); - auto x = hilti::visitor::dispatch(v, t->type(), [](const auto& v) { return v.result; }); + auto x = hilti::visitor::dispatch(v, t->type(), [](const auto& v) -> const auto& { return v.result; }); if ( ! x ) { std::cerr << t->dump(); logger().internalError(fmt("codegen: type %s does not have a visitor", *t), t); @@ -1088,7 +1088,7 @@ std::optional CodeGen::typeDeclaration(QualifiedType* t) return {}; auto v = VisitorDeclaration(this, t, &_cache_types_declarations); - return hilti::visitor::dispatch(v, t->type(), [](const auto& v) { return v.result; }); + return hilti::visitor::dispatch(v, t->type(), [](const auto& v) -> const auto& { return v.result; }); }; const CxxTypeInfo& CodeGen::_getOrCreateTypeInfo(QualifiedType* t) { @@ -1116,7 +1116,8 @@ const CxxTypeInfo& CodeGen::_getOrCreateTypeInfo(QualifiedType* t) { [&]() { auto v = VisitorTypeInfoPredefined(this); - if ( auto x = hilti::visitor::dispatch(v, t->type(), [](const auto& v) { return v.result; }); x && *x ) + if ( auto x = hilti::visitor::dispatch(v, t->type(), [](const auto& v) -> const auto& { return v.result; }); + x && *x ) return CxxTypeInfo{.predefined = true, .reference = fmt("&%s", *x)}; auto forward = cxx::declaration::Constant(tid, "::hilti::rt::TypeInfo", {}, "extern"); @@ -1129,11 +1130,11 @@ const CxxTypeInfo& CodeGen::_getOrCreateTypeInfo(QualifiedType* t) { return ti; auto v = VisitorTypeInfoDynamic(this, t); - auto x = hilti::visitor::dispatch(v, t->type(), [](const auto& v) { return v.result; }); + auto x = hilti::visitor::dispatch(v, t->type(), [](const auto& v) -> const auto& { return v.result; }); if ( ! x ) logger().internalError(fmt("codegen: type %s does not have a dynamic type info visitor", *t), t); - auto id_init = (t->type()->typeID() ? fmt("\"%s\"", t->type()->typeID()) : std::string("{}")); + const auto& id_init = (t->type()->typeID() ? fmt("\"%s\"", t->type()->typeID()) : std::string("{}")); auto init = fmt("{ %s, \"%s\", new %s }", id_init, util::escapeUTF8(display.str(), util::render_style::UTF8::EscapeQuotes), *x); diff --git a/hilti/toolchain/src/compiler/codegen/unpack.cc b/hilti/toolchain/src/compiler/codegen/unpack.cc index 331114f50..6bf249b38 100644 --- a/hilti/toolchain/src/compiler/codegen/unpack.cc +++ b/hilti/toolchain/src/compiler/codegen/unpack.cc @@ -88,7 +88,8 @@ struct Visitor : hilti::visitor::PreOrder { cxx::Expression CodeGen::pack(Expression* data, const Expressions& args) { auto cxx_args = util::transform(args, [&](const auto& e) { return compile(e, false); }); auto v = Visitor(this, Visitor::Kind::Pack, nullptr, compile(data), cxx_args); - if ( auto result = hilti::visitor::dispatch(v, data->type()->type(), [](const auto& v) { return v.result; }) ) + if ( auto result = + hilti::visitor::dispatch(v, data->type()->type(), [](const auto& v) -> const auto& { return v.result; }) ) return cxx::Expression(*result); logger().internalError("pack failed to compile", data->type()); @@ -96,7 +97,7 @@ cxx::Expression CodeGen::pack(Expression* data, const Expressions& args) { cxx::Expression CodeGen::pack(QualifiedType* t, const cxx::Expression& data, const std::vector& args) { auto v = Visitor(this, Visitor::Kind::Pack, nullptr, data, args); - if ( auto result = hilti::visitor::dispatch(v, t->type(), [](const auto& v) { return v.result; }) ) + if ( auto result = hilti::visitor::dispatch(v, t->type(), [](const auto& v) -> const auto& { return v.result; }) ) return cxx::Expression(*result); logger().internalError("pack failed to compile", t); @@ -106,7 +107,7 @@ cxx::Expression CodeGen::unpack(QualifiedType* t, QualifiedType* data_type, Expr bool throw_on_error) { auto cxx_args = util::transform(args, [&](const auto& e) { return compile(e, false); }); auto v = Visitor(this, Visitor::Kind::Unpack, data_type, compile(data), cxx_args); - if ( auto result = hilti::visitor::dispatch(v, t->type(), [](const auto& v) { return v.result; }) ) { + if ( auto result = hilti::visitor::dispatch(v, t->type(), [](const auto& v) -> const auto& { return v.result; }) ) { if ( throw_on_error ) return cxx::Expression(util::fmt("%s.valueOrThrow()", *result)); else @@ -119,7 +120,7 @@ cxx::Expression CodeGen::unpack(QualifiedType* t, QualifiedType* data_type, Expr cxx::Expression CodeGen::unpack(QualifiedType* t, QualifiedType* data_type, const cxx::Expression& data, const std::vector& args, bool throw_on_error) { auto v = Visitor(this, Visitor::Kind::Unpack, data_type, data, args); - if ( auto result = hilti::visitor::dispatch(v, t->type(), [](const auto& v) { return v.result; }) ) { + if ( auto result = hilti::visitor::dispatch(v, t->type(), [](const auto& v) -> const auto& { return v.result; }) ) { if ( throw_on_error ) return cxx::Expression(util::fmt("%s.valueOrThrow<::hilti::rt::InvalidValue>()", *result)); else diff --git a/hilti/toolchain/src/compiler/coercer.cc b/hilti/toolchain/src/compiler/coercer.cc index f92e209fa..4dcead2c5 100644 --- a/hilti/toolchain/src/compiler/coercer.cc +++ b/hilti/toolchain/src/compiler/coercer.cc @@ -60,7 +60,7 @@ struct VisitorCtor : visitor::PreOrder { return; } - result = builder->ctorMap(t->keyType(), t->elementType(), nelemns, n->meta()); + result = builder->ctorMap(t->keyType(), t->elementType(), std::move(nelemns), n->meta()); } } @@ -122,7 +122,7 @@ struct VisitorCtor : visitor::PreOrder { else return; } - result = builder->ctorSet(dt, nexprs, n->meta()); + result = builder->ctorSet(dt, std::move(nexprs), n->meta()); } } diff --git a/hilti/toolchain/src/compiler/cxx/linker.cc b/hilti/toolchain/src/compiler/cxx/linker.cc index bec9c0441..cfa1e4eab 100644 --- a/hilti/toolchain/src/compiler/cxx/linker.cc +++ b/hilti/toolchain/src/compiler/cxx/linker.cc @@ -29,8 +29,8 @@ void cxx::Linker::add(const linker::MetaData& md) { joins.push_back(j); } - if ( auto idx = md.globals_index; ! idx.id.empty() ) - _globals.insert(std::move(idx)); + if ( const auto& idx = md.globals_index; ! idx.id.empty() ) + _globals.insert(idx); } void cxx::Linker::finalize() { @@ -65,7 +65,7 @@ void cxx::Linker::finalize() { hash = rt::hashCombine(hash, std::hash()(content)); } - auto cxx_namespace = _codegen->context()->options().cxx_namespace_intern; + const auto& cxx_namespace = _codegen->context()->options().cxx_namespace_intern; auto scope = hilti::rt::fmt("%" PRIx64, hash); unit->add(fmt("const char HILTI_WEAK * %s_hlto_scope = \"%s\";", cxx_namespace, scope)); diff --git a/hilti/toolchain/src/compiler/cxx/unit.cc b/hilti/toolchain/src/compiler/cxx/unit.cc index 007f83d5e..3732c6dc6 100644 --- a/hilti/toolchain/src/compiler/cxx/unit.cc +++ b/hilti/toolchain/src/compiler/cxx/unit.cc @@ -83,7 +83,7 @@ void Unit::_addModuleInitFunction() { if ( _preinit_module ) register_.addStatement(fmt("__preinit_module()")); - auto id = addInitFunction(context().get(), register_, "__register_module"); + auto id = addInitFunction(context().get(), std::move(register_), "__register_module"); add(fmt("HILTI_PRE_INIT(%s)", id)); } } diff --git a/hilti/toolchain/src/compiler/driver.cc b/hilti/toolchain/src/compiler/driver.cc index 14bc25758..8595d0fdf 100644 --- a/hilti/toolchain/src/compiler/driver.cc +++ b/hilti/toolchain/src/compiler/driver.cc @@ -205,7 +205,7 @@ Result Driver::writeOutput(std::ifstream& in, const hilti::rt::filesyst Result Driver::writeToTemp(std::ifstream& in, const std::string& name_hint, const std::string& extension) { auto template_ = fmt("%s.XXXXXX.%s", name_hint, extension); - auto name = template_; + auto name = std::move(template_); auto fd = mkstemp(name.data()); if ( fd < 0 ) @@ -957,7 +957,7 @@ Result Driver::initRuntime() { config.show_backtraces = _driver_options.show_backtraces; config.report_resource_usage = _driver_options.report_resource_usage; config.enable_profiling = _driver_options.enable_profiling; - hilti::rt::configuration::set(config); + hilti::rt::configuration::set(std::move(config)); try { HILTI_DEBUG(logging::debug::Driver, "initializing runtime"); diff --git a/hilti/toolchain/src/compiler/jit.cc b/hilti/toolchain/src/compiler/jit.cc index c45ec9af5..017594c3d 100644 --- a/hilti/toolchain/src/compiler/jit.cc +++ b/hilti/toolchain/src/compiler/jit.cc @@ -208,7 +208,7 @@ hilti::Result> JIT::build() { } hilti::Result JIT::_checkCompiler() { - auto cxx = hilti::configuration().cxx; + const auto& cxx = hilti::configuration().cxx; // We ignore the output, just see if running the compiler works. `-dumpversion` // works with both GCC and clang, but unlikely to be supported by something @@ -290,7 +290,7 @@ hilti::Result JIT::_compile() { cc_files.push_back(cc); if ( ! keep_tmps ) - cc_files_generated.add(cc); + cc_files_generated.add(std::move(cc)); } // Compile all C++ files. @@ -342,7 +342,7 @@ hilti::Result JIT::_compile() { args.push_back(hilti::rt::filesystem::canonical(path)); auto cxx = hilti::configuration().cxx; - if ( const auto launcher = hilti::configuration().cxx_launcher; launcher && ! launcher->empty() ) { + if ( const auto& launcher = hilti::configuration().cxx_launcher; launcher && ! launcher->empty() ) { args.insert(args.begin(), cxx); cxx = *launcher; } diff --git a/hilti/toolchain/src/compiler/optimizer.cc b/hilti/toolchain/src/compiler/optimizer.cc index da8926ad3..d0fac2f90 100644 --- a/hilti/toolchain/src/compiler/optimizer.cc +++ b/hilti/toolchain/src/compiler/optimizer.cc @@ -444,7 +444,7 @@ struct FunctionVisitor : OptimizerVisitor { return; auto decl = n->op0()->as()->resolvedDeclaration(); - auto function_id = decl->fullyQualifiedID(); + const auto& function_id = decl->fullyQualifiedID(); assert(function_id); switch ( _stage ) { @@ -754,7 +754,7 @@ struct ConstantFoldingVisitor : OptimizerVisitor { case Stage::PRUNE_DECLS: return; case Stage::PRUNE_USES: { auto decl = n->resolvedDeclaration(); - auto id = decl->fullyQualifiedID(); + const auto& id = decl->fullyQualifiedID(); assert(id); if ( const auto& constant = _constants.find(id); constant != _constants.end() ) { @@ -1241,7 +1241,7 @@ class FeatureRequirementsVisitor : public visitor::MutatingPreOrder { if ( ! util::startsWith(id, "__feat") ) return {}; - const auto& tokens = util::split(id, "%"); + const auto& tokens = util::split(std::move(id), "%"); assert(tokens.size() == 3); auto type_id = ID(util::replace(tokens[1], "@@", "::")); @@ -1492,7 +1492,7 @@ struct MemberVisitor : OptimizerVisitor { if ( ! type_id ) break; - auto member_id = util::join({type_id, n->id()}, "::"); + auto member_id = util::join({std::move(type_id), n->id()}, "::"); // Record the member as used. _used[member_id] = true; @@ -1552,7 +1552,7 @@ void detail::optimizer::optimize(Builder* builder, ASTRoot* root) { util::timing::Collector _("hilti/compiler/optimizer"); const auto passes__ = rt::getenv("HILTI_OPTIMIZER_PASSES"); - const auto passes_ = + const auto& passes_ = passes__ ? std::optional(util::split(*passes__, ":")) : std::optional>(); auto passes = passes_ ? std::optional(std::set(passes_->begin(), passes_->end())) : std::optional>(); diff --git a/hilti/toolchain/src/compiler/resolver.cc b/hilti/toolchain/src/compiler/resolver.cc index e62f076c1..b3e494e20 100644 --- a/hilti/toolchain/src/compiler/resolver.cc +++ b/hilti/toolchain/src/compiler/resolver.cc @@ -166,7 +166,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { } if ( ! hook_id ) { - hook_id = canon_id; + hook_id = std::move(canon_id); hook_type = ftype; } else { @@ -848,7 +848,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { declaration::Type* linked_type = nullptr; Declaration* linked_prototype = nullptr; - if ( auto resolved = scope::lookupID(ns, n, "struct type") ) { + if ( auto resolved = scope::lookupID(std::move(ns), n, "struct type") ) { linked_type = resolved->first; for ( const auto& field : linked_type->type()->type()->as()->fields(n->id().local()) ) { @@ -1226,7 +1226,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { else id = n->id(); - auto resolved = scope::lookupID(id, scope_node, "declaration"); + auto resolved = scope::lookupID(std::move(id), scope_node, "declaration"); if ( resolved ) { auto index = context()->register_(resolved->first); n->setResolvedDeclarationIndex(context(), index); @@ -1360,7 +1360,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { if ( n->kind() == operator_::Kind::MemberCall ) { if ( auto stype = match->op0()->type()->type()->tryAs() ) { - auto id = match->op1()->as()->id(); + const auto& id = match->op1()->as()->id(); if ( auto field = stype->field(id) ) { auto ftype = field->type()->type()->as(); recordAutoParameters(*ftype, match->op2()); diff --git a/hilti/toolchain/src/compiler/type-unifier.cc b/hilti/toolchain/src/compiler/type-unifier.cc index a7aea6b4e..8e8c150ca 100644 --- a/hilti/toolchain/src/compiler/type-unifier.cc +++ b/hilti/toolchain/src/compiler/type-unifier.cc @@ -187,7 +187,7 @@ class VisitorTypeUnifier : public visitor::MutatingPostOrder { if ( unifier.isAborted() ) return; - auto serial = unifier.serialization(); + const auto& serial = unifier.serialization(); if ( serial.empty() ) { std::cerr << n->dump(); logger().internalError("empty type _serialization for unification, type not implemented?"); diff --git a/hilti/toolchain/src/compiler/unit.cc b/hilti/toolchain/src/compiler/unit.cc index 7b130156b..f73eccb3f 100644 --- a/hilti/toolchain/src/compiler/unit.cc +++ b/hilti/toolchain/src/compiler/unit.cc @@ -34,7 +34,7 @@ Result> Unit::fromCXX(const std::shared_ptr& cont std::shared_ptr cxx, const hilti::rt::filesystem::path& path) { auto uid = declaration::module::UID("", path.native()); - return std::shared_ptr(new Unit(context, uid, std::move(cxx))); + return std::shared_ptr(new Unit(context, std::move(uid), std::move(cxx))); } std::shared_ptr Unit::fromExistingUID(const std::shared_ptr& context, declaration::module::UID uid) { diff --git a/hilti/toolchain/src/compiler/validator.cc b/hilti/toolchain/src/compiler/validator.cc index 68e6380a9..8c32479f2 100644 --- a/hilti/toolchain/src/compiler/validator.cc +++ b/hilti/toolchain/src/compiler/validator.cc @@ -588,7 +588,7 @@ struct VisitorPost : visitor::PreOrder, public validator::VisitorMixIn { // Customized error message for calls to methods. std::vector context; - if ( auto candidates = operator_::registry().byMethodID(n->op1()->as()->id()); + if ( const auto& candidates = operator_::registry().byMethodID(n->op1()->as()->id()); ! candidates.empty() ) { // Apply heuristic on op0 to limit the candidates reported. std::vector cands; diff --git a/spicy/runtime/src/driver.cc b/spicy/runtime/src/driver.cc index 1a7b489d4..80002e041 100644 --- a/spicy/runtime/src/driver.cc +++ b/spicy/runtime/src/driver.cc @@ -242,7 +242,7 @@ void driver::ParsingStateForDriver::debug(const std::string& msg) { } void driver::ParsingState::debug(const std::string& msg, size_t size, const char* data) { - auto escaped = + const auto& escaped = data ? hilti::rt::escapeBytes(std::string(data, std::min(size_t(40), size))) : fmt("", size); debug(hilti::rt::fmt("%s: |%s%s|", msg, escaped, size > 40 ? "..." : "")); } @@ -494,7 +494,8 @@ Result Driver::processPreBatchedInput(std::istream& in) { context = std::move(ctx); } - if ( auto [x, ctx] = create_state(type, resp_parser_name, resp_id, cid, context); x != flows.end() ) + if ( auto [x, ctx] = create_state(type, resp_parser_name, resp_id, cid, std::move(context)); + x != flows.end() ) resp_state = &x->second; if ( ! (orig_state || resp_state) ) { diff --git a/spicy/runtime/src/parser.cc b/spicy/runtime/src/parser.cc index 3e905f9c1..1d799b07b 100644 --- a/spicy/runtime/src/parser.cc +++ b/spicy/runtime/src/parser.cc @@ -76,7 +76,7 @@ void detail::printParserState(std::string_view unit_id, const hilti::rt::ValueRe if ( i >= end ) return std::make_pair(hilti::rt::stream::View(begin, end), ""); - return std::make_pair(hilti::rt::stream::View(begin, i), "..."); + return std::make_pair(hilti::rt::stream::View(begin, std::move(i)), "..."); }; auto na = hilti::rt::Stream("n/a"); diff --git a/spicy/toolchain/src/ast/operators/unit.cc b/spicy/toolchain/src/ast/operators/unit.cc index fddbf5b1f..34450f4bf 100644 --- a/spicy/toolchain/src/ast/operators/unit.cc +++ b/spicy/toolchain/src/ast/operators/unit.cc @@ -14,7 +14,7 @@ namespace { namespace unit { void checkName(hilti::expression::ResolvedOperator* op) { - auto id = op->op1()->as()->id(); + const auto& id = op->op1()->as()->id(); auto i = op->op0()->type()->type()->as()->itemByName(id); if ( ! i ) @@ -24,7 +24,7 @@ void checkName(hilti::expression::ResolvedOperator* op) { QualifiedType* itemType(hilti::Builder* builder, const Expressions& operands) { auto unit = operands[0]->type()->type()->as(); - auto id = operands[1]->as()->id(); + const auto& id = operands[1]->as()->id(); if ( auto item = unit->itemByName(id) ) return item->itemType(); diff --git a/spicy/toolchain/src/compiler/codegen/codegen.cc b/spicy/toolchain/src/compiler/codegen/codegen.cc index af0b61fe1..9a7abda88 100644 --- a/spicy/toolchain/src/compiler/codegen/codegen.cc +++ b/spicy/toolchain/src/compiler/codegen/codegen.cc @@ -70,7 +70,7 @@ struct VisitorASTInfo : public visitor::PreOrder { return; } - auto lahs = unit->grammar().lookAheadsInUse(); + const auto& lahs = unit->grammar().lookAheadsInUse(); info->look_aheads_in_use.insert(lahs.begin(), lahs.end()); for ( const auto& [id, p] : unit->grammar().productions() ) { diff --git a/spicy/toolchain/src/compiler/codegen/grammar.cc b/spicy/toolchain/src/compiler/codegen/grammar.cc index 9cd305d2d..ea9f6d173 100644 --- a/spicy/toolchain/src/compiler/codegen/grammar.cc +++ b/spicy/toolchain/src/compiler/codegen/grammar.cc @@ -57,7 +57,7 @@ hilti::Result Grammar::setRoot(std::unique_ptr p) { if ( _root ) return hilti::result::Error("root production is already set"); - auto symbol = p->symbol(); + const auto& symbol = p->symbol(); if ( symbol.empty() ) return hilti::result::Error("root production must have a symbol"); @@ -164,14 +164,14 @@ bool Grammar::_add(std::map>* tbl, Production auto t = tbl->find(idx); assert(t != tbl->end()); - auto set = t->second; + const auto& set = t->second; auto union_ = hilti::util::setUnion(set, src); if ( union_.size() == set.size() ) // All in there already. return changed; - (*tbl)[idx] = union_; + (*tbl)[idx] = std::move(union_); return true; } diff --git a/spicy/toolchain/src/compiler/codegen/parser-builder.cc b/spicy/toolchain/src/compiler/codegen/parser-builder.cc index 4f49ee805..648663017 100644 --- a/spicy/toolchain/src/compiler/codegen/parser-builder.cc +++ b/spicy/toolchain/src/compiler/codegen/parser-builder.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include #include @@ -75,7 +74,7 @@ struct ProductionVisitor : public production::Visitor { auto cg() { return pb->cg(); } auto context() { return cg()->context(); } - auto state() { return pb->state(); } + const auto& state() { return pb->state(); } void pushState(ParserState p) { pb->pushState(std::move(p)); } void popState() { pb->popState(); } @@ -166,7 +165,7 @@ struct ProductionVisitor : public production::Visitor { auto missing = builder()->lower(builder()->memberCall(state().cur, "offset"), builder()->memberCall(ncur, "offset")); auto insufficient = builder()->addIf(missing); - pushBuilder(insufficient, [&]() { + pushBuilder(std::move(insufficient), [&]() { if ( field && ! field->isAnonymous() && ! field->isSkip() ) // Clear the field in case the type parsing has started // to fill it. @@ -185,7 +184,7 @@ struct ProductionVisitor : public production::Visitor { // We wrap the parsing of a non-atomic production into a new // function that's cached and reused. This ensures correct // operation for productions that recurse. - auto id = parse_functions.getOrCreate( + const auto& id = parse_functions.getOrCreate( p.symbol(), [&]() { return unit ? ID("__parse_stage1") : ID(fmt("__parse_%s_stage1", p.symbol())); }, [&](auto& id) { auto id_stage1 = id; @@ -242,7 +241,7 @@ struct ProductionVisitor : public production::Visitor { auto catch_ = try_->addCatch(builder()->parameter("__except", builder()->typeName("hilti::SystemException"))); - pushBuilder(catch_, [&]() { + pushBuilder(std::move(catch_), [&]() { pb->finalizeUnit(false, p.location()); run_finally(); builder()->addRethrow(); @@ -356,7 +355,7 @@ struct ProductionVisitor : public production::Visitor { {state().self, state().data, state().cur})); auto have_filter = builder()->addIf(filtered); - pushBuilder(have_filter); + pushBuilder(std::move(have_filter)); auto args2 = args; @@ -391,7 +390,7 @@ struct ProductionVisitor : public production::Visitor { } auto not_have_filter = builder()->addIf(builder()->not_(builder()->id("filtered"))); - pushBuilder(not_have_filter); + pushBuilder(std::move(not_have_filter)); builder()->addAssign(store_result, builder()->memberCall(state().self, id_stage2, args)); popBuilder(); @@ -653,8 +652,8 @@ struct ProductionVisitor : public production::Visitor { } if ( meta.field() ) { - Expression* default_ = - builder()->default_(builder()->typeName(unit->unitType()->typeID()), type_args, location); + Expression* default_ = builder()->default_(builder()->typeName(unit->unitType()->typeID()), + std::move(type_args), std::move(location)); builder()->addAssign(destination(), default_); } @@ -689,7 +688,7 @@ struct ProductionVisitor : public production::Visitor { auto catch_ = try_->second.addCatch(builder()->parameter("__except", builder()->typeName("hilti::SystemException"))); - pushBuilder(catch_, [&]() { + pushBuilder(std::move(catch_), [&]() { auto what = builder()->call("hilti::exception_what", {builder()->id("__except")}); builder()->addMemberCall(state().self, ID(fmt("__on_%s_error", field->id().local())), {what}, field->meta()); @@ -858,7 +857,7 @@ struct ProductionVisitor : public production::Visitor { auto cond = builder()->greaterEqual(builder()->memberCall(state().cur, "offset"), builder()->memberCall(state().ncur, "offset")); auto exceeded = builder()->addIf(cond); - pushBuilder(exceeded, [&]() { + pushBuilder(std::move(exceeded), [&]() { // We didn't finish parsing the data, which is an error. if ( ! field->isAnonymous() && ! field->isSkip() ) // Clear the field in case the type parsing has started to fill it. @@ -983,7 +982,7 @@ struct ProductionVisitor : public production::Visitor { auto ncur = builder()->addTmp("ncur", state().cur); auto ms = builder()->local("ms", builder()->memberCall(re, "token_matcher")); auto body = builder()->addWhile(ms, builder()->bool_(true)); - pushBuilder(body); + pushBuilder(std::move(body)); auto rc = builder()->addTmp("rc", builder()->typeSignedInteger(32)); builder()->addAssign(builder()->tuple({rc, ncur}), @@ -993,7 +992,7 @@ struct ProductionVisitor : public production::Visitor { // Match possible with additional data, continue matching. auto no_match_try_again = switch_.addCase(builder()->integer(-1)); - pushBuilder(no_match_try_again); + pushBuilder(std::move(no_match_try_again)); auto pstate = pb->state(); pstate.cur = ncur; pb->pushState(std::move(pstate)); @@ -1004,13 +1003,13 @@ struct ProductionVisitor : public production::Visitor { // No match found, leave `cur` unchanged. auto no_match = switch_.addCase(builder()->integer(0)); - pushBuilder(no_match); + pushBuilder(std::move(no_match)); builder()->addBreak(); popBuilder(); // Match found, update `cur`. auto match = switch_.addDefault(); - pushBuilder(match); + pushBuilder(std::move(match)); builder()->addAssign(state().cur, ncur); pb->trimInput(); builder()->addBreak(); @@ -1037,7 +1036,7 @@ struct ProductionVisitor : public production::Visitor { auto [true_, false_] = builder()->addIfElse(pb->atEod()); true_->addAssign(state().lahead, builder()->integer(look_ahead::Eod)); - pushBuilder(false_); + pushBuilder(std::move(false_)); // Collect all expected terminals. auto regexps = std::vector(); @@ -1072,7 +1071,7 @@ struct ProductionVisitor : public production::Visitor { builder()->addContinue(); }); - return pushBuilder(body); + return pushBuilder(std::move(body)); }; // Parse regexps in parallel. @@ -1096,8 +1095,8 @@ struct ProductionVisitor : public production::Visitor { } auto re = pb->cg()->addGlobalConstant( - builder()->ctorRegExp(flattened, builder()->attributeSet( - {builder()->attribute(hilti::attribute::Kind::Nosub)}))); + builder()->ctorRegExp(std::move(flattened), builder()->attributeSet({builder()->attribute( + hilti::attribute::Kind::Nosub)}))); // Create the token matcher state. builder()->addLocal(ID("ncur"), state().cur); auto ms = builder()->local("ms", builder()->memberCall(re, "token_matcher")); @@ -1186,7 +1185,7 @@ struct ProductionVisitor : public production::Visitor { auto ambiguous = true_->addIf( builder()->and_(builder()->unequal(state().lahead, builder()->integer(look_ahead::None)), builder()->equal(builder()->id("i"), state().lahead_end))); - pushBuilder(ambiguous); + pushBuilder(std::move(ambiguous)); pb->parseError("ambiguous look-ahead token match", location); popBuilder(); @@ -1215,8 +1214,8 @@ struct ProductionVisitor : public production::Visitor { parse(); auto [if_, else_] = builder()->addIfElse(builder()->or_(pb->atEod(), state().lahead)); - pushBuilder(if_, [&]() { builder()->addBreak(); }); - pushBuilder(else_, [&]() { pb->advanceToNextData(); }); + pushBuilder(std::move(if_), [&]() { builder()->addBreak(); }); + pushBuilder(std::move(else_), [&]() { pb->advanceToNextData(); }); }); break; @@ -1301,7 +1300,7 @@ struct ProductionVisitor : public production::Visitor { // `%synchronize-[at|after]`, so temporarily set a new value. auto pstate = state(); pstate.lahead = builder()->addTmp("sync_lahead", builder()->id("__lah")); - pushState(pstate); + pushState(std::move(pstate)); getLookAhead({ctor.get()}, id, ctor->location(), LiteralMode::Search); validateSearchResult(); @@ -1436,7 +1435,7 @@ struct ProductionVisitor : public production::Visitor { // for all subsequent fields is executed in this loop. For that reason // the loop bpdy needs to execute at least one time. auto while_ = builder()->addWhile(builder()->bool_(true)); - pushBuilder(while_); + pushBuilder(std::move(while_)); // Variable storing whether we actually entered trial mode. auto is_trial_mode = builder()->addTmp("is_trial_mode", builder()->bool_(false)); @@ -1473,7 +1472,7 @@ struct ProductionVisitor : public production::Visitor { builder()->addContinue(); }); - pushBuilder(body); + pushBuilder(std::move(body)); } /** End sync and trial mode. */ @@ -1614,7 +1613,7 @@ struct ProductionVisitor : public production::Visitor { cond = builder()->bool_(true); auto body = builder()->addWhile(cond); - pushBuilder(body); + pushBuilder(std::move(body)); auto cookie = pb->initLoopBody(); auto stop = parseProduction(*p->body()); auto b = builder()->addIf(stop); @@ -1639,16 +1638,16 @@ struct ProductionVisitor : public production::Visitor { for ( const auto& [exprs, prod] : p->cases() ) { auto case_ = switch_.addCase(exprs, prod->location()); - pushBuilder(case_, [&, &prod = prod]() { parseProduction(*prod); }); + pushBuilder(std::move(case_), [&, &prod = prod]() { parseProduction(*prod); }); } if ( auto prod = p->default_() ) { auto default_ = switch_.addDefault(prod->location()); - pushBuilder(default_, [&]() { parseProduction(*prod); }); + pushBuilder(std::move(default_), [&]() { parseProduction(*prod); }); } else { auto default_ = switch_.addDefault(p->location()); - pushBuilder(default_, [&]() { + pushBuilder(std::move(default_), [&]() { pb->parseError("no matching case in switch statement for value '%s'", {p->expression()}, p->location()); }); } @@ -1789,7 +1788,8 @@ struct ProductionVisitor : public production::Visitor { auto cond = builder()->greaterEqual(builder()->memberCall(state().cur, "offset"), builder()->memberCall(state().ncur, "offset")); auto exceeded = builder()->addIf(cond); - pushBuilder(exceeded, [&]() { pb->parseError("parsing not done within &max-size bytes", a->meta()); }); + pushBuilder(std::move(exceeded), + [&]() { pb->parseError("parsing not done within &max-size bytes", a->meta()); }); // Restore parser state. auto ncur = state().ncur; @@ -1816,7 +1816,7 @@ struct ProductionVisitor : public production::Visitor { // If we don't have a look-ahead symbol pending, get one. auto true_ = builder()->addIf(builder()->not_(state().lahead)); - pushBuilder(true_); + pushBuilder(std::move(true_)); getLookAhead(p); popBuilder(); @@ -1863,7 +1863,7 @@ struct ProductionVisitor : public production::Visitor { if ( ! eod_handled ) { auto builder_eod = switch_.addCase(builder()->integer(look_ahead::Eod)); - pushBuilder(builder_eod); + pushBuilder(std::move(builder_eod)); pb->parseError("expected look-ahead token, but reached end-of-data", p.location()); popBuilder(); } @@ -1879,15 +1879,16 @@ struct ProductionVisitor : public production::Visitor { void operator()(const production::LookAhead* p) final { auto [builder_alt1, builder_alt2, builder_default] = parseLookAhead(*p); - pushBuilder(builder_alt1); + pushBuilder(std::move(builder_alt1)); parseProduction(*p->alternatives().first); popBuilder(); - pushBuilder(builder_alt2); + pushBuilder(std::move(builder_alt2)); parseProduction(*p->alternatives().second); popBuilder(); - pushBuilder(builder_default, [&]() { pb->parseError("no expected look-ahead token found", p->location()); }); + pushBuilder(std::move(builder_default), + [&]() { pb->parseError("no expected look-ahead token found", p->location()); }); } void operator()(const production::Sequence* p) final { @@ -1914,7 +1915,7 @@ struct ProductionVisitor : public production::Visitor { if ( eod_attr ) { builder()->addDebugMsg("spicy-verbose", "- skipping to eod"); auto loop = builder()->addWhile(pb->waitForInputOrEod()); - pushBuilder(loop, [&]() { pb->advanceInput(builder()->size(state().cur)); }); + pushBuilder(std::move(loop), [&]() { pb->advanceInput(builder()->size(state().cur)); }); pb->advanceInput(builder()->size(state().cur)); } @@ -1926,7 +1927,7 @@ struct ProductionVisitor : public production::Visitor { auto until_bytes_size_var = builder()->addTmp("until_bytes_sz", builder()->size(until_bytes_var)); auto body = builder()->addWhile(builder()->bool_(true)); - pushBuilder(body, [&]() { + pushBuilder(std::move(body), [&]() { pb->waitForInput(until_bytes_size_var, "end-of-data reached before &until expression found", until_expr->meta()); @@ -1935,21 +1936,21 @@ struct ProductionVisitor : public production::Visitor { auto it_id = ID("it"); auto found = builder()->id(found_id); auto it = builder()->id(it_id); - builder()->addLocal(found_id, + builder()->addLocal(std::move(found_id), builder()->qualifiedType(builder()->typeBool(), hilti::Constness::Mutable)); - builder()->addLocal(it_id, builder()->qualifiedType(builder()->typeStreamIterator(), - hilti::Constness::Mutable)); + builder()->addLocal(std::move(it_id), builder()->qualifiedType(builder()->typeStreamIterator(), + hilti::Constness::Mutable)); builder()->addAssign(builder()->tuple({found, it}), find); auto [found_branch, not_found_branch] = builder()->addIfElse(found); - pushBuilder(found_branch, [&]() { + pushBuilder(std::move(found_branch), [&]() { auto new_it = builder()->sum(it, until_bytes_size_var); pb->advanceInput(new_it); builder()->addBreak(); }); - pushBuilder(not_found_branch, [&]() { pb->advanceInput(it); }); + pushBuilder(std::move(not_found_branch), [&]() { pb->advanceInput(it); }); }); } } @@ -1971,7 +1972,7 @@ struct ProductionVisitor : public production::Visitor { else { // Look-ahead based loop. auto body = builder()->addWhile(builder()->bool_(true)); - pushBuilder(body, [&]() { + pushBuilder(std::move(body), [&]() { // If we don't have any input right now, we suspend because // we might get an EOD next, in which case we need to abort the loop. builder()->addExpression(pb->waitForInputOrEod(builder()->integer(1))); @@ -2013,18 +2014,18 @@ struct ProductionVisitor : public production::Visitor { else { parse(); - pushBuilder(builder_default, [&]() { + pushBuilder(std::move(builder_default), [&]() { // Terminate loop. builder()->addBreak(); }); } - pushBuilder(builder_alt1, [&]() { + pushBuilder(std::move(builder_alt1), [&]() { // Terminate loop. builder()->addBreak(); }); - pushBuilder(builder_alt2, [&]() { + pushBuilder(std::move(builder_alt2), [&]() { // Parse body. auto cookie = pb->initLoopBody(); auto stop = parseProduction(*p->body()); @@ -2729,7 +2730,7 @@ void ParserBuilder::skip(Expression* size, const Meta& location) { auto n = builder()->addTmp("skip", size); auto loop = builder()->addWhile(builder()->greater(n, builder()->integer(0U))); - pushBuilder(loop, [&]() { + pushBuilder(std::move(loop), [&]() { waitForInput(builder()->integer(1U), "not enough bytes for skipping", location); auto consume = builder()->addTmp("consume", builder()->min(builder()->size(state().cur), n)); advanceInput(consume); @@ -2854,12 +2855,12 @@ void ParserBuilder::initBacktracking() { auto try_cur = builder()->addTmp("try_cur", state().cur); auto [body, try_] = builder()->addTry(); auto catch_ = try_.addCatch(builder()->parameter(ID("e"), builder()->typeName("spicy_rt::Backtrack"))); - pushBuilder(catch_, [&]() { builder()->addAssign(state().cur, try_cur); }); + pushBuilder(std::move(catch_), [&]() { builder()->addAssign(state().cur, try_cur); }); auto pstate = state(); pstate.trim = builder()->bool_(false); pushState(std::move(pstate)); - pushBuilder(body); + pushBuilder(std::move(body)); } void ParserBuilder::finishBacktracking() { diff --git a/spicy/toolchain/src/compiler/codegen/parsers/literals.cc b/spicy/toolchain/src/compiler/codegen/parsers/literals.cc index e624aad59..ab2fd8a7d 100644 --- a/spicy/toolchain/src/compiler/codegen/parsers/literals.cc +++ b/spicy/toolchain/src/compiler/codegen/parsers/literals.cc @@ -45,7 +45,7 @@ struct Visitor : public visitor::PreOrder { Expression* result = nullptr; auto pb() { return lp->pb; } - auto state() { return pb()->state(); } + const auto& state() { return pb()->state(); } auto builder() { return pb()->builder(); } auto context() { return pb()->context(); } auto pushBuilder(std::shared_ptr b) { return pb()->pushBuilder(std::move(b)); } @@ -84,7 +84,7 @@ struct Visitor : public visitor::PreOrder { if ( check_for_look_ahead ) { auto [have_lah, no_lah] = builder()->addIfElse(state().lahead); - pushBuilder(have_lah); + pushBuilder(std::move(have_lah)); pushBuilder(builder()->addIf( builder()->unequal(state().lahead, builder()->integer(lp->production->tokenID())))); @@ -104,7 +104,7 @@ struct Visitor : public visitor::PreOrder { pb()->consumeLookAhead(); popBuilder(); - pushBuilder(no_lah); + pushBuilder(std::move(no_lah)); } auto expect_bytes_literal = @@ -156,7 +156,7 @@ struct Visitor : public visitor::PreOrder { if ( check_for_look_ahead ) { auto [have_lah, no_lah] = builder()->addIfElse(state().lahead); - pushBuilder(have_lah); + pushBuilder(std::move(have_lah)); pushBuilder(builder()->addIf( builder()->unequal(state().lahead, builder()->integer(lp->production->tokenID())))); @@ -166,13 +166,13 @@ struct Visitor : public visitor::PreOrder { pb()->consumeLookAhead(result); popBuilder(); - pushBuilder(no_lah); + pushBuilder(std::move(no_lah)); } auto ncur = builder()->addTmp(ID("ncur"), state().cur); auto ms = builder()->local("ms", builder()->memberCall(re, "token_matcher")); auto body = builder()->addWhile(ms, builder()->bool_(true)); - pushBuilder(body); + pushBuilder(std::move(body)); auto rc = builder()->addTmp(ID("rc"), builder()->qualifiedType(builder()->typeSignedInteger(32), hilti::Constness::Mutable)); @@ -183,7 +183,7 @@ struct Visitor : public visitor::PreOrder { auto switch_ = builder()->addSwitch(rc, n->meta()); auto no_match_try_again = switch_.addCase(builder()->integer(-1)); - pushBuilder(no_match_try_again); + pushBuilder(std::move(no_match_try_again)); auto pstate = pb()->state(); pstate.self = builder()->expressionName(ID("self")); pstate.cur = ncur; @@ -197,12 +197,12 @@ struct Visitor : public visitor::PreOrder { popBuilder(); auto no_match_error = switch_.addCase(builder()->integer(0)); - pushBuilder(no_match_error); + pushBuilder(std::move(no_match_error)); pb()->parseError("failed to match regular expression", n->meta()); popBuilder(); auto match = switch_.addDefault(); - pushBuilder(match); + pushBuilder(std::move(match)); if ( state().literal_mode != LiteralMode::Skip ) { if ( state().captures ) @@ -258,7 +258,7 @@ struct Visitor : public visitor::PreOrder { if ( check_for_look_ahead ) { auto [have_lah, no_lah] = builder()->addIfElse(state().lahead); - pushBuilder(have_lah); + pushBuilder(std::move(have_lah)); pushBuilder(builder()->addIf( builder()->unequal(state().lahead, builder()->integer(lp->production->tokenID())))); @@ -268,7 +268,7 @@ struct Visitor : public visitor::PreOrder { pb()->consumeLookAhead(); popBuilder(); - pushBuilder(no_lah); + pushBuilder(std::move(no_lah)); } auto old_cur = builder()->addTmp("ocur", state().cur); @@ -281,7 +281,7 @@ struct Visitor : public visitor::PreOrder { builder()->unequal(x, expected)); auto error = builder()->addIf(no_match); - pushBuilder(error); + pushBuilder(std::move(error)); builder()->addAssign(state().cur, old_cur); pb()->parseError(fmt("expecting %u", *expected), meta); popBuilder(); @@ -332,7 +332,7 @@ struct Visitor : public visitor::PreOrder { if ( check_for_look_ahead ) { auto [have_lah, no_lah] = builder()->addIfElse(state().lahead); - pushBuilder(have_lah); + pushBuilder(std::move(have_lah)); pushBuilder(builder()->addIf( builder()->unequal(state().lahead, builder()->integer(lp->production->tokenID())))); @@ -346,7 +346,7 @@ struct Visitor : public visitor::PreOrder { pb()->consumeLookAhead(); popBuilder(); - pushBuilder(no_lah); + pushBuilder(std::move(no_lah)); } auto old_cur = builder()->addTmp("ocur", state().cur); @@ -384,13 +384,13 @@ struct Visitor : public visitor::PreOrder { auto new_cur = builder()->addTmp("ncur", state().cur); auto match = builder()->addIf(builder()->unequal(offset(old_cur), offset(new_cur))); - pushBuilder(match); + pushBuilder(std::move(match)); builder()->addAssign(state().cur, old_cur); // restore, because we must not move cur when in sync mode // Check that the bit values match what we expect. for ( const auto& b : n->bits() ) { auto error = builder()->addIf(builder()->unequal(builder()->member(bf, b->id()), b->expression())); - pushBuilder(error); + pushBuilder(std::move(error)); builder()->addAssign(new_cur, old_cur); // reset to old position popBuilder(); } diff --git a/spicy/toolchain/src/compiler/codegen/parsers/types.cc b/spicy/toolchain/src/compiler/codegen/parsers/types.cc index b09325ca3..d2f6766a2 100644 --- a/spicy/toolchain/src/compiler/codegen/parsers/types.cc +++ b/spicy/toolchain/src/compiler/codegen/parsers/types.cc @@ -31,7 +31,7 @@ struct TypeParser { Expression* buildParser(UnqualifiedType* t); - auto state() { return pb->state(); } + const auto& state() { return pb->state(); } auto builder() { return pb->builder(); } auto context() { return pb->context(); } auto pushBuilder(std::shared_ptr b) { return pb->pushBuilder(std::move(b)); } @@ -71,7 +71,7 @@ struct TypeParser { auto result = dst ? dst : builder()->addTmp("result", builder()->typeResult(qt)); auto true_ = builder()->addIf(has_data); - pushBuilder(true_); + pushBuilder(std::move(true_)); auto unpacked = builder()->deref(builder()->unpack(qt, unpack_args)); builder()->addAssign(builder()->tuple({result, state().cur}), unpacked); popBuilder(); @@ -169,7 +169,7 @@ struct Visitor : public visitor::PreOrder { if ( pb()->options().debug ) { auto have_value = builder()->addIf(builder()->hasMember(target, "__value__")); - pushBuilder(have_value, [&]() { + pushBuilder(std::move(have_value), [&]() { // Print all the bit ranges individually so that we can include // their IDs, which the standard tuple output wouldn't show. builder()->addDebugMsg("spicy", fmt("%s = %%s", tp->meta.field()->id()), @@ -303,11 +303,11 @@ struct Visitor : public visitor::PreOrder { if ( chunked_attr ) { auto loop = builder()->addWhile(builder()->bool_(true)); - pushBuilder(loop, [&]() { + pushBuilder(std::move(loop), [&]() { builder()->addLocal("more_data", pb()->waitForInputOrEod(builder()->integer(1))); auto have_data = builder()->addIf(builder()->size(state().cur)); - pushBuilder(have_data, [&]() { + pushBuilder(std::move(have_data), [&]() { builder()->addAssign(target, state().cur); pb()->advanceInput(builder()->size(state().cur)); @@ -359,7 +359,7 @@ struct Visitor : public visitor::PreOrder { builder()->addAssign(target, builder()->bytes("")); auto body = builder()->addWhile(builder()->bool_(true)); - pushBuilder(body, [&]() { + pushBuilder(std::move(body), [&]() { // Helper to add a new chunk of data to the field's value, // behaving slightly different depending on whether we have // &chunked or not. @@ -384,20 +384,20 @@ struct Visitor : public visitor::PreOrder { auto it_id = ID("it"); auto found = builder()->id(found_id); auto it = builder()->id(it_id); - builder()->addLocal(found_id, + builder()->addLocal(std::move(found_id), builder()->qualifiedType(builder()->typeBool(), hilti::Constness::Mutable)); - builder()->addLocal(it_id, builder()->qualifiedType(builder()->typeStreamIterator(), - hilti::Constness::Mutable)); + builder()->addLocal(std::move(it_id), builder()->qualifiedType(builder()->typeStreamIterator(), + hilti::Constness::Mutable)); builder()->addAssign(builder()->tuple({found, it}), find); Expression* match = builder()->memberCall(state().cur, "sub", {it}); auto non_empty_match = builder()->addIf(builder()->size(match)); - pushBuilder(non_empty_match, [&]() { add_match_data(target, match); }); + pushBuilder(std::move(non_empty_match), [&]() { add_match_data(target, match); }); auto [found_branch, not_found_branch] = builder()->addIfElse(found); - pushBuilder(found_branch, [&]() { + pushBuilder(std::move(found_branch), [&]() { auto new_it = builder()->sum(it, until_bytes_size_var); if ( until_including_attr ) @@ -407,7 +407,7 @@ struct Visitor : public visitor::PreOrder { builder()->addBreak(); }); - pushBuilder(not_found_branch, [&]() { pb()->advanceInput(it); }); + pushBuilder(std::move(not_found_branch), [&]() { pb()->advanceInput(it); }); }); result = target; diff --git a/spicy/toolchain/src/compiler/codegen/unit-builder.cc b/spicy/toolchain/src/compiler/codegen/unit-builder.cc index a1e74426f..108c5649a 100644 --- a/spicy/toolchain/src/compiler/codegen/unit-builder.cc +++ b/spicy/toolchain/src/compiler/codegen/unit-builder.cc @@ -444,9 +444,9 @@ void CodeGen::_compileParserRegistration(const ID& public_id, const ID& struct_i // Register the parser if the `is_filter` or `supports_sinks` features are // active; `public` units we always register (by passing an empty list of // features to the feature guard). - const auto dependentFeatureFlags = unit->isPublic() ? - std::vector{} : - std::vector({"is_filter", "supports_sinks"}); + const auto& dependentFeatureFlags = unit->isPublic() ? + std::vector{} : + std::vector({"is_filter", "supports_sinks"}); _pb.guardFeatureCode(unit, dependentFeatureFlags, [&]() { auto ty_mime_types = builder()->typeVector( diff --git a/spicy/toolchain/src/compiler/driver.cc b/spicy/toolchain/src/compiler/driver.cc index e40a30722..a351e403f 100644 --- a/spicy/toolchain/src/compiler/driver.cc +++ b/spicy/toolchain/src/compiler/driver.cc @@ -8,7 +8,7 @@ using namespace spicy; spicy::Options Driver::spicyCompilerOptions() const { spicy::Options options; - auto hilti_options = hiltiOptions(); + const auto& hilti_options = hiltiOptions(); options.track_offsets = hilti_options.getAuxOption("spicy.track_offsets", false); return options; } diff --git a/spicy/toolchain/src/compiler/resolver.cc b/spicy/toolchain/src/compiler/resolver.cc index 19fa5d0de..9d4ee308b 100644 --- a/spicy/toolchain/src/compiler/resolver.cc +++ b/spicy/toolchain/src/compiler/resolver.cc @@ -47,8 +47,8 @@ auto resolveField(Builder* builder, type::unit::item::UnresolvedField* u, T t) { u->removeChildren(0, {}); - auto field = builder->typeUnitItemField(u->fieldID(), std::move(t), u->isSkip(), arguments, repeat_count, sinks, - attributes, condition, std::move(hooks), u->meta()); + auto field = builder->typeUnitItemField(u->fieldID(), std::move(t), u->isSkip(), std::move(arguments), repeat_count, + std::move(sinks), attributes, condition, std::move(hooks), u->meta()); assert(u->index()); field->setIndex(*u->index()); return field; @@ -151,7 +151,8 @@ struct VisitorPass2 : visitor::MutatingPostOrder { // Implicitly create an error message from the condition itself. auto msg = hilti::util::fmt("&requires failed: %s", hilti::util::replace(cond->print(), "__dd", "$$")); auto new_cond = - builder()->conditionTest(*ne.coerced, builder()->expression(builder()->ctorError(msg)), cond->meta()); + builder()->conditionTest(*ne.coerced, builder()->expression(builder()->ctorError(std::move(msg))), + cond->meta()); n->replaceChild(context(), cond, new_cond); recordChange(n, std::string(to_string(n->kind()))); } @@ -225,7 +226,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { // Produce a tailored error message if `%XXX` is used on a unit field. if ( auto id = ns.namespace_(); id && hilti::util::startsWith(n->id().local(), "0x25_") ) { if ( auto resolved = - hilti::scope::lookupID(id, n, "unit type") ) { + hilti::scope::lookupID(std::move(id), n, "unit type") ) { if ( auto utype = resolved->first->template as() ->type() ->type() @@ -365,7 +366,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { void operator()(operator_::unit::HasMember* n) final { auto unit = n->op0()->type()->type()->tryAs(); - auto id = n->op1()->tryAs()->id(); + const auto& id = n->op1()->tryAs()->id(); if ( unit && id && ! unit->itemByName(id) ) { // See if we got an anonymous bitfield with a member of that @@ -383,7 +384,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { void operator()(operator_::unit::MemberConst* n) final { auto unit = n->op0()->type()->type()->tryAs(); - auto id = n->op1()->tryAs()->id(); + const auto& id = n->op1()->tryAs()->id(); if ( unit && id && ! unit->itemByName(id) ) { // See if we got an anonymous bitfield with a member of that @@ -404,7 +405,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { void operator()(operator_::unit::MemberNonConst* n) final { auto unit = n->op0()->type()->type()->tryAs(); - auto id = n->op1()->tryAs()->id(); + const auto& id = n->op1()->tryAs()->id(); if ( unit && id && ! unit->itemByName(id) ) { // See if we got an anonymous bitfield with a member of that @@ -425,7 +426,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { void operator()(operator_::unit::TryMember* n) final { auto unit = n->op0()->type()->type()->tryAs(); - auto id = n->op1()->tryAs()->id(); + const auto& id = n->op1()->tryAs()->id(); if ( unit && id && ! unit->itemByName(id) ) { // See if we we got an anonymous bitfield with a member of that diff --git a/spicy/toolchain/src/compiler/validator.cc b/spicy/toolchain/src/compiler/validator.cc index 76f53734d..995da4655 100644 --- a/spicy/toolchain/src/compiler/validator.cc +++ b/spicy/toolchain/src/compiler/validator.cc @@ -986,7 +986,7 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { void operator()(spicy::type::unit::item::UnresolvedField* n) final { if ( auto id = n->unresolvedID() ) { // Re-lookup ID to see if it exists at all. - if ( auto resolved = hilti::scope::lookupID(id, n, "field"); ! resolved ) + if ( auto resolved = hilti::scope::lookupID(std::move(id), n, "field"); ! resolved ) error(resolved.error(), n, node::ErrorPriority::High); if ( n->hasErrors() ) From ee76fa2535db75d299257c82bb0fc2d4ea630222 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Thu, 9 Jan 2025 11:50:30 +0100 Subject: [PATCH 06/13] Prevent potential nullptr dereference. --- hilti/toolchain/src/ast/ast-context.cc | 5 +++-- hilti/toolchain/src/compiler/resolver.cc | 2 +- spicy/toolchain/src/ast/types/unit-items/field.cc | 11 ++++++++--- spicy/toolchain/src/compiler/codegen/codegen.cc | 9 +++++++++ .../toolchain/src/compiler/codegen/grammar-builder.cc | 6 +++++- spicy/toolchain/src/compiler/validator.cc | 3 ++- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/hilti/toolchain/src/ast/ast-context.cc b/hilti/toolchain/src/ast/ast-context.cc index daaf2415a..5b6b56695 100644 --- a/hilti/toolchain/src/ast/ast-context.cc +++ b/hilti/toolchain/src/ast/ast-context.cc @@ -439,8 +439,9 @@ void ASTContext::replace(Declaration* old, Declaration* new_) { _declarations_by_index[index.value()] = new_; new_->setDeclarationIndex(index); - if ( auto n = new_->tryAs() ) { - auto o = old->tryAs(); + auto* n = new_->tryAs(); + auto* o = old->tryAs(); + if ( n && o ) { n->type()->type()->setDeclarationIndex(index); replace(o->type()->type(), n->type()->type()); } diff --git a/hilti/toolchain/src/compiler/resolver.cc b/hilti/toolchain/src/compiler/resolver.cc index b3e494e20..3dad71c21 100644 --- a/hilti/toolchain/src/compiler/resolver.cc +++ b/hilti/toolchain/src/compiler/resolver.cc @@ -169,7 +169,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { hook_id = std::move(canon_id); hook_type = ftype; } - else { + else if ( hook_type ) { if ( canon_id != hook_id || ! type::same(ftype, hook_type) ) return false; } diff --git a/spicy/toolchain/src/ast/types/unit-items/field.cc b/spicy/toolchain/src/ast/types/unit-items/field.cc index d3c9912ef..630021bd2 100644 --- a/spicy/toolchain/src/ast/types/unit-items/field.cc +++ b/spicy/toolchain/src/ast/types/unit-items/field.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -53,9 +54,13 @@ struct SizeVisitor : hilti::visitor::PreOrder { void operator()(hilti::type::Bitfield* n) final { result = builder->integer(n->width() / 8U); } void operator()(hilti::type::Real*) final { - auto type = *field.attributes()->find(hilti::attribute::Kind::Type)->valueAsExpression(); - result = builder->ternary(builder->equal(type, builder->id("spicy::RealType::IEEE754_Single")), - builder->integer(4U), builder->integer(8U)); + auto* type = field.attributes()->find(hilti::attribute::Kind::Type); + if ( ! type ) + hilti::logger().internalError("real value must have a &type attribute"); + + result = + builder->ternary(builder->equal(*type->valueAsExpression(), builder->id("spicy::RealType::IEEE754_Single")), + builder->integer(4U), builder->integer(8U)); } }; diff --git a/spicy/toolchain/src/compiler/codegen/codegen.cc b/spicy/toolchain/src/compiler/codegen/codegen.cc index 9a7abda88..ca9f18d16 100644 --- a/spicy/toolchain/src/compiler/codegen/codegen.cc +++ b/spicy/toolchain/src/compiler/codegen/codegen.cc @@ -626,7 +626,14 @@ hilti::declaration::Function* CodeGen::compileHook(const type::Unit& unit, const } } + auto assert_field = [&]() { + if ( ! field ) + hilti::logger().internalError(fmt("cannot find field '%s' in unit '%'", id, unit.typeID())); + }; + if ( type == declaration::hook::Type::ForEach ) { + assert_field(); + params.push_back( builder()->parameter("__dd", field->ddType()->type()->elementType()->type(), hilti::parameter::Kind::In)); params.push_back(builder()->parameter("__stop", builder()->typeBool(), hilti::parameter::Kind::InOut)); @@ -636,6 +643,8 @@ hilti::declaration::Function* CodeGen::compileHook(const type::Unit& unit, const params.push_back(builder()->parameter("__excpt", builder()->typeString(), hilti::parameter::Kind::In)); } else if ( original_field_type ) { + assert_field(); + params.push_back(builder()->parameter("__dd", field->itemType()->type(), hilti::parameter::Kind::In)); // Pass on captures for fields of type regexp, which are the only diff --git a/spicy/toolchain/src/compiler/codegen/grammar-builder.cc b/spicy/toolchain/src/compiler/codegen/grammar-builder.cc index fd86b72b3..7a17836fb 100644 --- a/spicy/toolchain/src/compiler/codegen/grammar-builder.cc +++ b/spicy/toolchain/src/compiler/codegen/grammar-builder.cc @@ -1,5 +1,7 @@ // Copyright (c) 2020-2023 by the Zeek Project. See LICENSE for details. +#include + #include #include #include @@ -323,7 +325,9 @@ struct Visitor : public visitor::PreOrder { auto unit = std::make_unique(context(), pid, n, args, std::move(items), n->meta().location()); // This takes ownership of the unit production, storing it inside the grammar. - pf->grammar->resolve(dynamic_cast(unresolved.get()), std::move(unit)); + auto* deferred = dynamic_cast(unresolved.get()); + assert(deferred); + pf->grammar->resolve(deferred, std::move(unit)); result = std::move(unresolved); } diff --git a/spicy/toolchain/src/compiler/validator.cc b/spicy/toolchain/src/compiler/validator.cc index 995da4655..c747dd397 100644 --- a/spicy/toolchain/src/compiler/validator.cc +++ b/spicy/toolchain/src/compiler/validator.cc @@ -465,7 +465,8 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { checkNodeAttributes(n->nodeTag(), n->attributes(), "type declaration"); if ( n->linkage() == hilti::declaration::Linkage::Public && n->type()->alias() ) { - if ( n->type()->alias()->resolvedDeclaration()->linkage() != hilti::declaration::Linkage::Public ) + if ( auto* resolved = n->type()->alias()->resolvedDeclaration(); + resolved && resolved->linkage() != hilti::declaration::Linkage::Public ) error("public unit alias cannot refer to a non-public type", n); } } From ede54b48a31ccdeb63d2620981b7dc9109776c86 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Thu, 9 Jan 2025 12:25:53 +0100 Subject: [PATCH 07/13] Drop dereference of end iterator. --- hilti/runtime/src/util.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hilti/runtime/src/util.cc b/hilti/runtime/src/util.cc index 6355b4ccb..ead2ada5c 100644 --- a/hilti/runtime/src/util.cc +++ b/hilti/runtime/src/util.cc @@ -433,12 +433,13 @@ std::string hilti::rt::strftime(const std::string& format, const hilti::rt::Time hilti::rt::Time hilti::rt::strptime(const std::string& buf, const std::string& format) { tm time; - auto end = ::strptime(buf.c_str(), format.c_str(), &time); + const char* end = ::strptime(buf.data(), format.c_str(), &time); if ( ! end ) throw InvalidArgument("could not parse time string"); - if ( end != &*buf.end() ) + auto consumed = std::distance(buf.data(), end); + if ( static_cast(consumed) != buf.size() ) throw InvalidArgument(hilti::rt::fmt("unparsed remainder after parsing time string: %s", end)); // If the struct tm object was obtained from POSIX strptime or equivalent From 6fc414d4b2ede99f264c33f9ce5b064d34889be6 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Thu, 9 Jan 2025 13:01:04 +0100 Subject: [PATCH 08/13] Prevent exception escape. --- hilti/runtime/src/main.cc | 6 ++- hilti/toolchain/bin/hilti-config.cc | 8 ++- hilti/toolchain/bin/hiltic.cc | 7 ++- spicy/toolchain/bin/spicy-config.cc | 8 ++- spicy/toolchain/bin/spicy-doc.cc | 8 ++- spicy/toolchain/bin/spicy-driver.cc | 68 ++++++++++++-------------- spicy/toolchain/bin/spicy-dump/main.cc | 66 ++++++++++++------------- spicy/toolchain/bin/spicyc.cc | 5 +- 8 files changed, 96 insertions(+), 80 deletions(-) diff --git a/hilti/runtime/src/main.cc b/hilti/runtime/src/main.cc index 539a0fa4c..db057fded 100644 --- a/hilti/runtime/src/main.cc +++ b/hilti/runtime/src/main.cc @@ -5,6 +5,7 @@ #include +#include #include #include @@ -51,4 +52,7 @@ int HILTI_WEAK hilti::main(int argc, char** argv) { return 0; } -int HILTI_WEAK main(int argc, char** argv) { return hilti::main(argc, argv); } +int HILTI_WEAK main(int argc, char** argv) try { return hilti::main(argc, argv); } catch ( const std::exception& e ) { + hilti::rt::fatalError(hilti::rt::fmt("terminating with uncaught exception of type %s: %s", + hilti::rt::demangle(typeid(e).name()), e.what())); +} diff --git a/hilti/toolchain/bin/hilti-config.cc b/hilti/toolchain/bin/hilti-config.cc index c8f631dd0..b2c246584 100644 --- a/hilti/toolchain/bin/hilti-config.cc +++ b/hilti/toolchain/bin/hilti-config.cc @@ -2,11 +2,13 @@ // // Outputs paths and flags for using HILTI. +#include #include #include #include #include +#include #include using namespace std; @@ -48,8 +50,7 @@ static void join(std::vector& a, const std::vector& b) { a.insert(a.end(), b.begin(), b.end()); } -// NOLINTNEXTLINE(bugprone-exception-escape) -int main(int argc, char** argv) { +int main(int argc, char** argv) try { bool want_debug = false; bool want_dynamic_linking = false; @@ -223,4 +224,7 @@ int main(int argc, char** argv) { cout << hilti::util::join(result.begin(), result.end(), " ") << '\n'; return 0; +} catch ( const std::exception& e ) { + hilti::logger().fatalError(hilti::util::fmt("terminating with uncaught exception of type %s: %s", + hilti::util::demangle(typeid(e).name()), e.what())); } diff --git a/hilti/toolchain/bin/hiltic.cc b/hilti/toolchain/bin/hiltic.cc index 68267a3a0..7c98ac5a2 100644 --- a/hilti/toolchain/bin/hiltic.cc +++ b/hilti/toolchain/bin/hiltic.cc @@ -1,9 +1,11 @@ // Copyright (c) 2020-2023 by the Zeek Project. See LICENSE for details. +#include + #include #include -int main(int argc, char** argv) { +int main(int argc, char** argv) try { hilti::init(); hilti::Driver driver("hiltic", hilti::util::currentExecutable()); @@ -22,4 +24,7 @@ int main(int argc, char** argv) { } return 0; +} catch ( const std::exception& e ) { + hilti::logger().fatalError(hilti::util::fmt("terminating with uncaught exception of type %s: %s", + hilti::util::demangle(typeid(e).name()), e.what())); } diff --git a/spicy/toolchain/bin/spicy-config.cc b/spicy/toolchain/bin/spicy-config.cc index 8635e5512..3bb658bb4 100644 --- a/spicy/toolchain/bin/spicy-config.cc +++ b/spicy/toolchain/bin/spicy-config.cc @@ -2,11 +2,13 @@ // // Outputs paths and flags for using Spicy. +#include #include #include #include #include +#include #include #include @@ -52,8 +54,7 @@ static void join(std::vector& a, const std::vector& b) { a.insert(a.end(), b.begin(), b.end()); } -// NOLINTNEXTLINE(bugprone-exception-escape) -int main(int argc, char** argv) { +int main(int argc, char** argv) try { bool want_debug = false; bool want_dynamic_linking = false; @@ -248,4 +249,7 @@ int main(int argc, char** argv) { cout << hilti::util::join(result.begin(), result.end(), " ") << '\n'; return 0; +} catch ( const std::exception& e ) { + hilti::logger().fatalError(hilti::util::fmt("terminating with uncaught exception of type %s: %s", + hilti::util::demangle(typeid(e).name()), e.what())); } diff --git a/spicy/toolchain/bin/spicy-doc.cc b/spicy/toolchain/bin/spicy-doc.cc index 5d5c62663..ba9020397 100644 --- a/spicy/toolchain/bin/spicy-doc.cc +++ b/spicy/toolchain/bin/spicy-doc.cc @@ -1,5 +1,7 @@ // Copyright (c) 2020-2023 by the Zeek Project. See LICENSE for details. +#include + #include #include @@ -113,8 +115,7 @@ class SpicyDoc : public spicy::Driver { } }; -// NOLINTNEXTLINE(bugprone-exception-escape) -int main(int argc, char** argv) { +int main(int argc, char** argv) try { hilti::init(); spicy::init(); @@ -205,4 +206,7 @@ int main(int argc, char** argv) { std::cout << all_operators.dump(4) << '\n'; return 0; +} catch ( const std::exception& e ) { + hilti::logger().fatalError(hilti::util::fmt("terminating with uncaught exception of type %s: %s", + hilti::util::demangle(typeid(e).name()), e.what())); } diff --git a/spicy/toolchain/bin/spicy-driver.cc b/spicy/toolchain/bin/spicy-driver.cc index 3ebde9382..a69ebadaf 100644 --- a/spicy/toolchain/bin/spicy-driver.cc +++ b/spicy/toolchain/bin/spicy-driver.cc @@ -264,8 +264,7 @@ void SpicyDriver::parseOptions(int argc, char** argv) { } } -// NOLINTNEXTLINE(bugprone-exception-escape) -int main(int argc, char** argv) { +int main(int argc, char** argv) try { hilti::init(); spicy::init(); @@ -281,51 +280,45 @@ int main(int argc, char** argv) { if ( auto x = driver.compile(); ! x ) driver.fatalError(x.error()); - try { - if ( auto x = driver.initRuntime(); ! x ) - driver.fatalError(x.error()); - - for ( const auto& parser : driver.opt_parser_aliases ) { - auto m = hilti::util::transform(hilti::util::split(parser, "="), - [](const auto& x) { return hilti::util::trim(x); }); + if ( auto x = driver.initRuntime(); ! x ) + driver.fatalError(x.error()); - if ( m.size() != 2 ) - driver.fatalError("invalid alias specification: must be of form '='"); + for ( const auto& parser : driver.opt_parser_aliases ) { + auto m = + hilti::util::transform(hilti::util::split(parser, "="), [](const auto& x) { return hilti::util::trim(x); }); - if ( auto rc = spicy::rt::registerParserAlias(m[1], m[0]); ! rc ) - driver.fatalError(fmt("invalid alias specification: %s", rc.error())); - } + if ( m.size() != 2 ) + driver.fatalError("invalid alias specification: must be of form '='"); - if ( driver.opt_list_parsers ) - driver.listParsers(std::cout, driver.opt_list_parsers > 1); + if ( auto rc = spicy::rt::registerParserAlias(m[1], m[0]); ! rc ) + driver.fatalError(fmt("invalid alias specification: %s", rc.error())); + } - else { - std::ifstream in(driver.opt_file, std::ios::in | std::ios::binary); + if ( driver.opt_list_parsers ) + driver.listParsers(std::cout, driver.opt_list_parsers > 1); - if ( ! in.is_open() ) - driver.fatalError("cannot open input for reading"); + else { + std::ifstream in(driver.opt_file, std::ios::in | std::ios::binary); - if ( driver.opt_input_is_batch ) { - if ( auto x = driver.processPreBatchedInput(in); ! x ) - driver.fatalError(x.error()); - } - else { - auto parser = driver.lookupParser(driver.opt_parser); - if ( ! parser ) - driver.fatalError(parser.error()); + if ( ! in.is_open() ) + driver.fatalError("cannot open input for reading"); - if ( auto x = driver.processInput(**parser, in, driver.opt_increment); ! x ) - driver.fatalError(x.error()); - } + if ( driver.opt_input_is_batch ) { + if ( auto x = driver.processPreBatchedInput(in); ! x ) + driver.fatalError(x.error()); } + else { + auto parser = driver.lookupParser(driver.opt_parser); + if ( ! parser ) + driver.fatalError(parser.error()); - driver.finishRuntime(); - - } catch ( const std::exception& e ) { - driver.fatalError(hilti::util::fmt("terminating with uncaught exception of type %s: %s", - hilti::util::demangle(typeid(e).name()), e.what())); + if ( auto x = driver.processInput(**parser, in, driver.opt_increment); ! x ) + driver.fatalError(x.error()); + } } + driver.finishRuntime(); + if ( driver.driverOptions().report_times ) hilti::util::timing::summary(std::cerr); @@ -335,4 +328,7 @@ int main(int argc, char** argv) { return 1; return 0; +} catch ( const std::exception& e ) { + SpicyDriver().fatalError(hilti::util::fmt("terminating with uncaught exception of type %s: %s", + hilti::util::demangle(typeid(e).name()), e.what())); } diff --git a/spicy/toolchain/bin/spicy-dump/main.cc b/spicy/toolchain/bin/spicy-dump/main.cc index 25448f4a5..5954df76a 100644 --- a/spicy/toolchain/bin/spicy-dump/main.cc +++ b/spicy/toolchain/bin/spicy-dump/main.cc @@ -217,8 +217,7 @@ void SpicyDump::parseOptions(int argc, char** argv) { } } -// NOLINTNEXTLINE(bugprone-exception-escape) -int main(int argc, char** argv) { +int main(int argc, char** argv) try { hilti::init(); spicy::init(); @@ -233,50 +232,47 @@ int main(int argc, char** argv) { // user so we're just reporting a generic message here. fatalError("aborting after errors"); - try { - auto config = hilti::rt::configuration::get(); + auto config = hilti::rt::configuration::get(); - if ( ! driver.opt_enable_print ) - config.cout.reset(); + if ( ! driver.opt_enable_print ) + config.cout.reset(); - hilti::rt::configuration::set(std::move(config)); + hilti::rt::configuration::set(std::move(config)); - if ( auto x = driver.initRuntime(); ! x ) - fatalError(x.error().description()); + if ( auto x = driver.initRuntime(); ! x ) + fatalError(x.error().description()); - if ( driver.opt_list_parsers ) - driver.listParsers(std::cout, driver.opt_list_parsers > 1); + if ( driver.opt_list_parsers ) + driver.listParsers(std::cout, driver.opt_list_parsers > 1); - else { - auto parser = driver.lookupParser(driver.opt_parser); - if ( ! parser ) - fatalError(parser.error()); + else { + auto parser = driver.lookupParser(driver.opt_parser); + if ( ! parser ) + fatalError(parser.error()); - std::ifstream in(driver.opt_file, std::ios::in | std::ios::binary); + std::ifstream in(driver.opt_file, std::ios::in | std::ios::binary); - if ( ! in.is_open() ) - fatalError("cannot open stdin for reading"); + if ( ! in.is_open() ) + fatalError("cannot open stdin for reading"); - auto unit = driver.processInput(**parser, in); - if ( ! unit ) - fatalError(unit.error()); + auto unit = driver.processInput(**parser, in); + if ( ! unit ) + fatalError(unit.error()); - if ( driver.opt_json ) - JSONPrinter(std::cout, driver.output_options).print(unit->value()); - else { - TextPrinter(std::cout, driver.output_options).print(unit->value()); - std::cout << '\n'; - } + if ( driver.opt_json ) + JSONPrinter(std::cout, driver.output_options).print(unit->value()); + else { + TextPrinter(std::cout, driver.output_options).print(unit->value()); + std::cout << '\n'; } - - driver.finishRuntime(); - - } catch ( const std::exception& e ) { - std::cerr << hilti::util::fmt("[fatal error] terminating with uncaught exception of type %s: %s", - hilti::util::demangle(typeid(e).name()), e.what()) - << '\n'; - exit(1); } + driver.finishRuntime(); + return 0; +} catch ( const std::exception& e ) { + std::cerr << hilti::util::fmt("[fatal error] terminating with uncaught exception of type %s: %s", + hilti::util::demangle(typeid(e).name()), e.what()) + << '\n'; + exit(1); } diff --git a/spicy/toolchain/bin/spicyc.cc b/spicy/toolchain/bin/spicyc.cc index ab5bc5520..8f95f0437 100644 --- a/spicy/toolchain/bin/spicyc.cc +++ b/spicy/toolchain/bin/spicyc.cc @@ -19,7 +19,7 @@ class Spicyc : public spicy::Driver { void hookFinishRuntime() override { spicy::rt::done(); } }; -int main(int argc, char** argv) { +int main(int argc, char** argv) try { hilti::init(); spicy::init(); @@ -40,4 +40,7 @@ int main(int argc, char** argv) { driver.finishRuntime(); return 1; } +} catch ( const std::exception& e ) { + hilti::logger().fatalError(hilti::util::fmt("terminating with uncaught exception of type %s: %s", + hilti::util::demangle(typeid(e).name()), e.what())); } From 9bdaee70de8cd757ac5cb154881c646c406882e8 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Thu, 9 Jan 2025 13:15:53 +0100 Subject: [PATCH 09/13] Avoid throwing never handled exception in low-level helper function. --- hilti/toolchain/include/base/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hilti/toolchain/include/base/util.h b/hilti/toolchain/include/base/util.h index ff65f88be..c552706a7 100644 --- a/hilti/toolchain/include/base/util.h +++ b/hilti/toolchain/include/base/util.h @@ -607,7 +607,7 @@ constexpr auto to_string(Enum value, const Value (&values)[Size]) { if ( v.value == value ) return v.name; - throw std::out_of_range(std::to_string(static_cast(value))); + rt::internalError(fmt("enum value '%s' out of range", static_cast(value))); }; } // namespace enum_ From c1f144b6cdf41d0d48202b1f30db280ce8de6285 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Thu, 9 Jan 2025 15:08:46 +0100 Subject: [PATCH 10/13] Prevent destructor from throwing. --- hilti/toolchain/src/compiler/driver.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hilti/toolchain/src/compiler/driver.cc b/hilti/toolchain/src/compiler/driver.cc index 8595d0fdf..1255949c7 100644 --- a/hilti/toolchain/src/compiler/driver.cc +++ b/hilti/toolchain/src/compiler/driver.cc @@ -72,7 +72,11 @@ Driver::Driver(std::string name, const hilti::rt::filesystem::path& argv0) : _na Driver::~Driver() { if ( _driver_options.report_times ) - util::timing::summary(std::cerr); + try { + util::timing::summary(std::cerr); + } catch ( ... ) { + // Nothing. + } if ( ! _driver_options.keep_tmps ) { for ( const auto& t : _tmp_files ) From 3eda5e3b1d0712d3aaff0515609a16332899d85c Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Thu, 9 Jan 2025 15:33:06 +0100 Subject: [PATCH 11/13] Avoid theoretical exception in widely used helper function. --- hilti/runtime/src/debug-logger.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hilti/runtime/src/debug-logger.cc b/hilti/runtime/src/debug-logger.cc index 70a4ac1fd..84984b0c5 100644 --- a/hilti/runtime/src/debug-logger.cc +++ b/hilti/runtime/src/debug-logger.cc @@ -1,5 +1,7 @@ // Copyright (c) 2020-2023 by the Zeek Project. See LICENSE for details. +#include + #include #include @@ -42,7 +44,12 @@ void detail::DebugLogger::print(std::string_view stream, std::string_view msg) { } } - auto indent = std::string(i->second * 2, ' '); + // Theoretically the ident computation could overflow, but in that case we + // would have already run into trouble elsewhere (e.g., giant strings from + // huge ident widths). Instead perform the computation with overflow which + // for unsigned integers is defined and wraps around. + static_assert(std::is_unsigned_vsecond.Ref())>>); + auto indent = std::string(i->second.Ref() * 2, ' '); (*_output) << fmt("[%s] %s%s", stream, indent, msg) << '\n'; _output->flush(); } From 7daf25016b62e0f042d24af5da70fff432c150d4 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Thu, 9 Jan 2025 15:51:12 +0100 Subject: [PATCH 12/13] Prevent exception in generic `noexcept` function. --- hilti/runtime/include/types/reference.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hilti/runtime/include/types/reference.h b/hilti/runtime/include/types/reference.h index 461119ce8..6d17fafbe 100644 --- a/hilti/runtime/include/types/reference.h +++ b/hilti/runtime/include/types/reference.h @@ -261,13 +261,13 @@ class ValueReference { */ ValueReference& operator=(ValueReference&& other) noexcept { if ( &other != this ) { - // We can't move the actual value as other references may be - // referring to it. - *_get() = *other._get(); - - // Some implementations for `std::variant` do not have a `noexpect` - // move assignment operator. + // Not all types wrapped in a `ValueReference` might have a + // `noexcept` (move) assignment operator. try { + // We can't move the actual value as other references may be + // referring to it. + *_get() = *other._get(); + other._ptr = nullptr; } catch ( ... ) { cannot_be_reached(); From 3b677c10c9785d9fdc85e40a34d41529d253a6be Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Fri, 10 Jan 2025 08:04:25 +0100 Subject: [PATCH 13/13] Address a FIXME. I believe the issue documented in the FIXME was a problem with some older stdlib implementation/compiler versions. Drop it since it seems to work fine now. --- hilti/toolchain/src/base/util.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hilti/toolchain/src/base/util.cc b/hilti/toolchain/src/base/util.cc index 18ae294ce..8202372ed 100644 --- a/hilti/toolchain/src/base/util.cc +++ b/hilti/toolchain/src/base/util.cc @@ -45,9 +45,7 @@ std::vector util::split(std::string s, const std::string& delim) { l.push_back(s.substr(0, p)); - // FIXME: Don't understand why directly assigning to s doesn't work. - std::string t = s.substr(p + delim.size(), std::string::npos); - s = std::move(t); + s = s.substr(p + delim.size(), std::string::npos); } l.push_back(s);